这道题还是比较基础的状态压缩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;
}