ural False Mirrors (状态压缩+记忆化搜索)

2024-08-28 10:18

本文主要是介绍ural False Mirrors (状态压缩+记忆化搜索),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://acm.timus.ru/problem.aspx?space=1&num=1152


有n个阳台围城一圈,每个阳台都有若干个怪兽,一次可以打三个相邻的阳台上的怪兽,它们就会全部死去,但攻击者会受到没有死去怪兽的攻击,每个怪兽的攻击是1unit,问最后攻击者受到的最小伤害。


n <= 20,可以直接dfs过去。

1次WA,1次TLE。

WA是没看透题意,我判断的递归终止的条件是怪兽数目小于等于3,这是不对的,就算怪兽数目小于等于3,也不一定能一次打完,因为它只能打连续的怪兽,若两个怪兽之间的距离大于等于2,那么还需要一次才能打完。

TLE因为没加剪枝,dfs的过程中一旦发现已受攻击值大于最优值,就返回。


#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL __int64
#define eps 1e-12
#define PI acos(-1.0)
#define PP pair<LL,LL>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000;
const int mod = 1000000009;int a[22],vis[22];
int Min;
int n;
void dfs(int num,int sum,int att)
{if(att >= Min) //TLE的关键!return;if(num == 1){Min = min(Min,att);return;}//判断没死的怪兽的位置是否相邻,只有相邻递归才结束else if(num == 2){int p[3],cnt=0;for(int i = 1; i <= n; i++)if(!vis[i])p[++cnt] = i;if(p[2] - p[1] <= 1 || p[2]-p[1] == n-1){Min = min(Min,att);return;}}else if(num == 3){int p[3],cnt = 0;for(int i = 1; i <= n; i++){if(!vis[i]){if(i <= n-2 && !vis[i+1] && !vis[i+2]){Min = min(Min,att);return;}else if(!vis[n-1] && !vis[n] && !vis[1]){Min = min(Min,att);return;}}}}for(int i = 1; i <= n; i++){if(!vis[i]){int tmp = 0,f1 = 0,f2 = 0,t;vis[i] = 1;tmp += a[i];if(i > 1 && !vis[i-1]){vis[i-1] = 1;tmp += a[i-1];f1 = 1;}else if(i == 1 && !vis[n]){vis[n] = 1;tmp += a[n];f1 = 1;}if(i < n && !vis[i+1]){vis[i+1] = 1;tmp += a[i+1];f2 = 1;}else if(i == n && !vis[1]){vis[1] = 1;tmp += a[1];f2 = 1;}t = sum - tmp;dfs(num-1-f1-f2,t,att+t);vis[i] = 0;if(i > 1 && f1 == 1)vis[i-1] = 0;else if(i == 1 && f1 == 1)vis[n] = 0;if(i < n && f2 == 1)vis[i+1] = 0;else if(i == n && f2 == 1)vis[1] = 0;}}
}int main()
{int sum;while(~scanf("%d",&n)){sum = 0;for(int i = 1; i <= n; i++){scanf("%d",&a[i]);sum += a[i];}Min = INF;memset(vis,0,sizeof(vis));dfs(n,sum,0);printf("%d\n",Min);}return 0;
}


又换了一种新姿势,因为n<=20,且每个怪物在一种状态下只有0和1两个选择,所以共有(1<<n)-1种状态,然后记忆化搜索。


#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL __int64
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 50010;int n,num[22];
int dp[(1<<20)+10];int dfs(int sta)
{if(dp[sta] != INF)return dp[sta];int ss,a,b;for(int i = 1; i <= n; i++){if(sta&(1<<(i-1))){ss = sta;a = (i == 1?n:i-1);b = (i == n?1:i+1);ss -= (1<<(i-1));if(ss&(1<<(a-1)))ss -= (1<<(a-1));if(ss&(1<<(b-1)))ss -= (1<<(b-1));int tmp = 0;for(int j = 1; j <= n; j++)if(ss & (1<<(j-1)) )tmp += num[j];dp[sta] = min(dp[sta],dfs(ss)+tmp);}}return dp[sta];
}int main()
{while(~scanf("%d",&n)){for(int i = 1; i <= n; i++)scanf("%d",&num[i]);memset(dp,INF,sizeof(dp));dp[0] = 0;printf("%d\n",dfs((1<<n)-1));}return 0;
}


这篇关于ural False Mirrors (状态压缩+记忆化搜索)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114480

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu1565(状态压缩)

本人第一道ac的状态压缩dp,这题的数据非常水,很容易过 题意:在n*n的矩阵中选数字使得不存在任意两个数字相邻,求最大值 解题思路: 一、因为在1<<20中有很多状态是无效的,所以第一步是选择有效状态,存到cnt[]数组中 二、dp[i][j]表示到第i行的状态cnt[j]所能得到的最大值,状态转移方程dp[i][j] = max(dp[i][j],dp[i-1][k]) ,其中k满足c

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大

状态dp总结

zoj 3631  N 个数中选若干数和(只能选一次)<=M 的最大值 const int Max_N = 38 ;int a[1<<16] , b[1<<16] , x[Max_N] , e[Max_N] ;void GetNum(int g[] , int n , int s[] , int &m){ int i , j , t ;m = 0 ;for(i = 0 ;

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

hdu3006状态dp

给你n个集合。集合中均为数字且数字的范围在[1,m]内。m<=14。现在问用这些集合能组成多少个集合自己本身也算。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.Inp

hdu4277搜索

给你n个有长度的线段,问如果用上所有的线段来拼1个三角形,最多能拼出多少种不同的? import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动