这道题还是比较基础的状态压缩dp,但有几个点还是要去注意一下,注意点代码的注释中已经给出来了。
//poj 1038 状态压缩dp #include<stdio.h> #include<cstdlib> #include<istream> #include<algorithm> #include<vector> #include<string.h> #define mod 105225319 #define maxn 100000 using namespace std; int dp[3][maxn]; //0:表示前两个都没有;1:表示前第二个有,前一个没有:2:表示前一个有。 int N,M,K,man=1,map[165][15]; int cal(int q[]) { int i,j=1,ans=0; for(i=1;i<=M;i++) { ans+=max(q[i]-1,0)*j; j*=3; } return ans; } void transform_(int sta,int f[]) { int i,j=1; for(i=2;i<=M;i++) j*=3; for(i=1;i<=M;i++) { f[M-i+1]=sta/j; sta=sta%j; j/=3; } return; } void dfs(int row,int cow,int q[],int cnt) //注意这里的状态转移不能直接用dp[]=dp[]来进行,因为不满足后效性,因为搜索并不是按0-n的顺序进行的,因此dp[i]的值未必会是最终的值,在后面会发生改变。 { if(cow-1>M) return; int tt=cal(q); int qq[20]; memset(qq,0,sizeof(qq)); dp[row%2][tt]=max(dp[row%2][tt],cnt); dfs(row,cow+1,q,cnt); if(q[cow]==0&&q[cow+1]==0&&cow+1<=M&&!map[row][cow]&&row>=3&&!map[row][cow+1]&&!map[row-1][cow]&&!map[row-1][cow+1]&&!map[row-2][cow]&&!map[row-2][cow+1]) { for(int i=1;i<=15;i++) qq[i]=q[i]; qq[cow]=qq[cow+1]=3; dfs(row,cow+2,qq,cnt+1); memset(qq,0,sizeof(qq)); } if(q[cow]<=1&&q[cow+1]<=1&&q[cow+2]<=1&&cow+2<=M&&row>=2&&!map[row-1][cow]&&!map[row-1][cow+1]&&!map[row-1][cow+2]&&!map[row][cow]&&!map[row][cow+1]&&!map[row][cow+2]) { for(int i=1;i<=20;i++) qq[i]=q[i]; qq[cow]=qq[cow+1]=qq[cow+2]=3; dfs(row,cow+3,qq,cnt+1); memset(qq,0,sizeof(qq)); } return; } int main() { int T, TT = 1; //freopen("d:\\in.txt","r",stdin); //freopen("d:\\inn.txt","w",stdout); scanf("%d",&T); while(T) { scanf("%d%d%d",&N,&M,&K); int i; memset(map,0,sizeof(map)); memset(dp,-1,sizeof(dp)); for(i=1;i<=K;i++) { int x,y; scanf("%d%d",&x,&y); map[x][y]=1; } man=1; for(i=1;i<=M;i++) man*=3; for(i=0;i<=man;i++) dp[0][i]=-1; dp[0][man-1]=0; for(i=1;i<=N;i++) { for(int jj=0;jj<=man;jj++) dp[i%2][jj]=-1; for(int s=0;s<man;s++) { if(dp[(i+1)%2][s]==-1) continue; int ds[20]; memset(ds,0,sizeof(ds)); transform_(s,ds); //printf("s=%d i=%d\n",s,i); dfs(i,1,ds,dp[(i+1)%2][s]); } } int answ=0; for(i=0;i<man;i++) answ=max(dp[N%2][i],answ); printf("%d\n",answ); T--; } return 0; }