题意:在n*m的棋盘中,求2*3木块的最大覆盖数(不允许木块重叠,且有些无法覆盖的点)。
做法:3进制压缩状态,此时的状态会用数组记录,而且为了方便,数组从 0开始,表示每一行的状态,而行数是从1开始记录的,所以在记录无法覆盖的点的时候要注意这个改变,否则。。。,写挫了,人品好才没超时1800MS,伤不起。。。
#include<stdio.h> #include<string.h> bool blo[150][12]; short dp[155][60000]; int state1[12],state2[12]; int pow[12]; int n,m; //行列已经翻转。 inline short max(short a,short b) { return a>b?a:b; } void work(void) { pow[0]=1; for(int i=1;i<=10;i++) pow[i]=3*pow[i-1]; } int ctod(int *state) { int i,s=0; for(i=0;i<m;i++) s+=state[i]*pow[i]; return s; } void dtoc(int s,int *state) { for(int i=0;i<m;i++,s/=3) state[i]=s%3; } void init() { int i; memset(state2,0,sizeof(state2)); for(i=0;i<m;i++) state1[i]=1; dp[0][ctod(state1)]=0; } void dfs(int i,int lie,int get) { if(lie>=m) { int x=ctod(state1); dp[i][x]=max(dp[i][x],get); return ; } dfs(i,lie+1,get); if(lie+2<m&&blo[i][lie]==0&&blo[i][lie+1]==0&&blo[i][lie+2]==0 &&blo[i+1][lie]==0&&blo[i+1][lie+1]==0&&blo[i+1][lie+2]==0 &&state1[lie]==0&&state1[lie+1]==0&&state1[lie+2]==0) { state1[lie]=state1[lie+1]=state1[lie+2]=2; dfs(i,lie+3,get+1); state1[lie]=state1[lie+1]=state1[lie+2]=0; } if(lie+1<m&&state2[lie]==0&&state2[lie+1]==0&&state1[lie]==0&&state1[lie+1]==0 &&blo[i][lie]==0&&blo[i][lie+1]==0&&blo[i-1][lie]==0&&blo[i-1][lie+1]==0 &&blo[i+1][lie]==0&&blo[i+1][lie+1]==0) { state1[lie]=state1[lie+1]=2; dfs(i,lie+2,get+1); state1[lie]=state1[lie+1]=0; } } int main() { int i,D,k,j; short ans; work(); scanf("%d",&D); while(D--) { scanf("%d%d%d",&n,&m,&k); memset(dp,-1,sizeof(dp)); memset(blo,0,sizeof(blo)); while(k--) { int x,y; scanf("%d%d",&x,&y); y--;//就是这里了,要注意。。。。 blo[x][y]=1; } init(); for(i=1;i<n;i++) for(j=0;j<pow[m];j++) if(dp[i-1][j]!=-1) { dtoc(j,state2); for(int t=0;t<m;t++) state1[t]=(state2[t]-1>0); dfs(i,0,dp[i-1][j]); } ans=0; for(j=0;j<pow[m];j++) ans=max(ans,dp[n-1][j]); printf("%d\n",ans); } return 0; }