您的位置:首页 > 其它

【DP,状态压缩】PKU-1038-Bugs Integrated, Inc.

2012-02-25 22:41 375 查看
黑书上的一道较难的DP,用到了三进制状态压缩……虽然开始时有点思路,但是很多细节都不会处理,只能模仿人家的代码了……菜……

有三个状态,0表示前两行为空,1表示只有前一行为空,2表示前一行不空……dp[i][j],i表示第几行,j表示某一种状态……

#include<iostream>
using namespace std;
int m,a[10],b[10],c[11];
short dp[151][59049];
int h(int a[])
{
int res=0,i;
for(i=0;i<m;i++)res+=a[i]*c[i];
return res;
}
void f(int a[],int s)
{
int i;
for(i=0;i<m;i++,s/=3)
a[i]=s%3;
}
void dfs(int i,int x,int s,int d)
{
if(x==m)
{
if(dp[i][s]<d)dp[i][s]=d;
return;
}
if(x+1<m&&!a[x]&&!a[x+1]&&!b[x]&&!b[x+1])              //这里放一块2x3的芯片
dfs(i,x+2,s+c[x]*2+c[x+1]*2,d+1);
if(x+2<m&&!b[x]&&!b[x+1]&&!b[x+2])              //这里放一块3x2的芯片
dfs(i,x+3,s+c[x]*2+c[x+1]*2+c[x+2]*2,d+1);
dfs(i,x+1,s,d);            //这里不放芯片
}
int main()
{
//freopen("a.txt","r",stdin);
int i,j,k,l,n,s,t,x,y,res;
bool map[151][10];
c[0]=1;
for(i=1;i<11;i++)c[i]=3*c[i-1];
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
memset(map,0,sizeof(map));
memset(dp,-1,sizeof(dp));
for(i=0;i<k;i++)
{
scanf("%d%d",&x,&y);
map[x][y-1]=1;
}
for(i=0;i<m;i++)
{
if(map[1][i])a[i]=2;
else a[i]=1;
}
s=h(a);
dp[1][s]=0;
for(i=2;i<=n;i++)
for(j=0;j<c[m];j++)
{
if(dp[i-1][j]==-1)continue;
f(a,j);              //构造i-1行初始状态
for(l=0;l<m;l++)
{
if(map[i][l])b[l]=2;
else
{
if(a[l]==2)b[l]=1;           //构造i行初始状态
else b[l]=0;
}
}
s=h(b);
dfs(i,0,s,dp[i-1][j]);
}
res=0;
for(i=0;i<c[m];i++)
if(res<dp
[i])res=dp
[i];
printf("%d\n",res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: