hdu 4272 LianLianKan (贪心可水过,不过正解是状态压缩)
http://acm.hdu.edu.cn/showproblem.php?pid=4272
题意:
给你一个数字栈,每次必须从栈顶开始往下找距离<=5的范围内,如果存在与栈顶相同的数字,则两个数字同时出栈,其余数字还在栈中保持相对位置不变。
思路:
比赛时,这道题目相当坑爹,才开始写的是<5 VON想到贪心模拟,可是我出了两组数据一组数据按最近贪不对,另一组按最远贪也不对。于是我们纠结啊。。。。后来知道题目出错,是<=5于是贪心水过。后来才发现贪心是不对的
这组数据:
12
1 2 2 1 3 1 1 1 1 1 1 3
应该输出0可是输出1也对。。我对这题无语了。。。我处理成<=7也对。
状态压缩,看的别人的解题报告。我想我现在的水平还没有到达这个高度,真心不好想。。。。继续加油。。
我们将设每次都是在<=5的范围内取最远的与之相同(两数出栈),则5个连续的出栈之后会形成0101010101也就是说我们只要维护一个长度为10的序列即可,只要后面存在与之相同的肯定在这10个序列里面。状态转移方程不好说,代码中讲解:
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string> #define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b) #define ll long long #define inf 0x7f7f7f7f #define MOD 100000007 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100007 #define M 100007 #define N 1007 using namespace std; //freopen("din.txt","r",stdin); int a[N],dp[N][1<<11]; int dfs(int dep,int msk){ if (dep < 0){ if (msk == 0) return 1; else return 0; } if (dp[dep][msk] != -1) return dp[dep][msk]; int &res = dp[dep][msk]; res = 0; //栈顶元素已经出栈 if (!(msk&(1<<9))){ int nsk = msk<<1; if (dep - 10 >= 0) nsk |= 1;//十个之后还有就不上来 res = dfs(dep - 1,nsk); } //栈顶元素未出栈 else{ int ct = 0; int use = 0; int nsk = msk^(1<<9);//首先删除栈顶元素 for (int i = 8; i >= 0; --i){ ct++; if (nsk&(1<<i)){//往后查找与之相同的元素 if (a[dep - ct] == a[dep]){ int tmp = nsk^(1<<i); tmp <<= 1; if (dep - 10 >= 0) tmp |= 1; res = dfs(dep - 1,tmp); } if (res == 1) break;//找到就跳出 use++; if (use >= 5) break;//保持距离<=5 } } } return res; } int main(){ //freopen("din.txt","r",stdin); int i,j; int n; while (~scanf("%d",&n)){ for (i = 0; i < n; ++i) scanf("%d",&a[i]); int state = 0; //去前十个的状态1表示未出栈0表示出栈 for (i = n - 1,j = 0; i >= 0 && j <= 9; --i, ++j) state = (state<<1) + 1; //不足十个补0 while (j <= 9){ state <<= 1; ++j; } CL(dp,-1); int mk = dfs(n - 1,state); printf("%d\n",mk); } return 0; }