标签:cout cin 状压 name nbsp 思路 开始 main namespace
题意:就是连连看,有两个相同的就能消除,再加上两个特别的规定,一是只能从栈顶开始消除,而是两个相同的元素之间距离不能超过6,询问能否消除序列中所有元素。
思路:数据水,贪心就能过,但严谨的考虑,贪心显然不能解决所有问题。这题虽然序列很长,但是状态并不复杂,可以使用滚动的状压dp,然后考虑使用多少位表示状态,每一种状态表示第i位为栈首的序列状态,该位前最多能消除掉该位后四位,所以我们只需要表示后9位的状态即可,总计10位。
某位上1表示该位已被消除,0表示未被消除。
dp[i][j]表示从i位开始的10位,能否达到j状态。
#include <cstdio> #include <iostream> #include <cstring> using namespace std; const int maxn=1e3+10; const int up=1<<10; const int bit=9; int dp[maxn][up]; int a[maxn]; int n; int main() { while(cin>>n) { for(int i=n;i>=1;i--) scanf("%d",a+i); memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=n;i++) { for(int j=0;j<up;j++) { if(!dp[i-1][j]) continue;//该状态不存在,跳过 if(j&1) dp[i][j>>1]=1;//该位已经消除 else{ int cnt=0;//表示序列中已经被消除的数 for(int k=1;k<=bit;k++) { if(!((j>>k)&1)&&k-cnt<=5&&i+k<=n&&a[i]==a[i+k]) { dp[i][j>>1|(1<<k-1)]=1; } else if((j>>k)&1) cnt++; } } } } if(dp[n][0]) cout<<1<<endl; else cout<<0<<endl; } }
标签:cout cin 状压 name nbsp 思路 开始 main namespace
原文地址:https://www.cnblogs.com/npunch/p/12364312.html