题目:https://www.luogu.org/problemnew/show/P2593
DP的话,考虑到当前这一位只跟前两位有关,所以记录一下这3位的状态就行;
于是一开始记录的第 i 位,i-1 位的数量,i-2 位的数量,是否有过对子,然后可行性DP;
但是写得太丑,又WA又T...

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,a[105]; bool f[105][105][105][3]; int rd() { int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return ret*f; } int main() { scanf("%d",&n); while(n--) { memset(a,0,sizeof a); memset(f,0,sizeof f); for(int i=1;i<=100;i++)a[i]=rd(); f[0][0][0][0]=1; for(int i=1;i<=100;i++) for(int j=0;j<=(i-2>0?a[i-2]:0);j++) for(int k=j;k<=(i-1>0?a[i-1]:0);k++) if(f[i-1][j][k][0]||f[i-1][j][k][1]) { if(a[i]>=j)f[i][k-j][a[i]-j][0]=f[i-1][j][k][0]; if(a[i]>=j)f[i][k-j][a[i]-j][1]=f[i-1][j][k][1]; if(a[i]-j>=2&&f[i-1][j][k][0])f[i][k-j][a[i]-j-2][1]=1; for(int l=1;a[i]-j>=3*l;l++) { if(a[i]-j>=3*l) { f[i][k-j][a[i]-j-3*l][0]=f[i-1][j][k][0]; f[i][k-j][a[i]-j-3*l][1]=f[i-1][j][k][1]; } if(a[i]-j>=4*l) { f[i][k-j][a[i]-j-4*l][0]=f[i-1][j][k][0]; f[i][k-j][a[i]-j-4*l][1]=f[i-1][j][k][1]; } } } if(f[100][0][0][1])printf("Yes "); else printf("No "); } return 0; }
于是放弃这个写法了...
看到TJ,记录的是第 i 位和第 i-1 位的数量,这样就可以同层转移啦!于是简洁好多;
但总感觉复杂度有点不对啊,这样最高不是 10^8 吗...总之加上 register 就卡过去了。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,a[105]; bool f[105][105][105][3]; int rd() { int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return ret*f; } int main() { n=rd(); while(n--) { memset(f,0,sizeof f); for(register int i=1;i<=100;i++)a[i]=rd(); f[0][0][0][0]=1; for(register int i=1;i<=100;i++) for(register int j=0;j<=(i-1>0?a[i-1]:0);j++) for(register int k=0;k<=a[i];k++) { if(k>=2)f[i][j][k][1]|=f[i][j][k-2][0];//可以同层转移囧 if(k>=3)f[i][j][k][0]|=f[i][j][k-3][0],f[i][j][k][1]|=f[i][j][k-3][1]; if(k>=4)f[i][j][k][0]|=f[i][j][k-4][0],f[i][j][k][1]|=f[i][j][k-4][1]; if(k<=j&&k<=a[i-2])f[i][j][k][0]|=f[i-1][a[i-2]-k][j-k][0], f[i][j][k][1]|=f[i-1][a[i-2]-k][j-k][1]; } if(f[100][a[99]][a[100]][1])printf("Yes "); else printf("No "); } return 0; }