一个公司生产一种2*3规模的芯片,但是原材料上面有一些地方是不能用来当作芯片材料的,给出原料大小,及上面不能做原料的点,问你怎么分解,可以使生成芯片最大化。
对M进行三进制状压
last数组存储第i-1行和i-2行状态,cur数组存储i行和i-1行状态
cur[k]=2; // 本行k位置和上行k位置都不可用
cur[k]=1; // 本行k位置可用,上行k位置不可用
cur[k]=0; // 本行和上行位置k均可用
必须用滚动数组,否则爆内存
#include "stdio.h"
#include "string.h"
int b[20],ans,n,m;
int dp[2][69050],last[21],cur[21],map[160][160];
int updata(int i,int j)
{
int res,k;
res=0;
memset(cur,0,sizeof(cur));
memset(last,0,sizeof(last));
for (k=1;k<=m;k++)
{last[k]=j%3; j/=3;}
for (k=1;k<=m;k++)
if (map[i][k]==1)
{
cur[k]=2; // 本行k位置和上行k位置都不可用
res+=b[k]*2;
}else
if (last[k]==2) // 上一行 k位置被占,上上行k位置没有被占
{
cur[k]=1; // 本行k位置可用,上行k位置不可用
res+=b[k];
}
else
cur[k]=0; // 本行和上行位置k均可用
return res; // 本行位置压缩值
}
void dfs(int i,int now,int k,int status) // 第i行,价值为now,当前放第k个,状压值status
{
int temp;
if (now>ans) ans=now;
if (now>dp[i][status]) dp[i][status]=now;
if (k+1<=m && cur[k]==0 && cur[k+1]==0 && last[k]==0 && last[k+1]==0) // 本行,上行,上上行的k和k+1位置均可用
{
cur[k]=2;
cur[k+1]=2;
temp=status+b[k]*2+b[k+1]*2;
dfs(i,now+1,k+2,temp);
cur[k]=0;
cur[k+1]=0;
}// 放置3行*2列 矩阵
if (k+2<=m && cur[k]==0 && cur[k+1]==0 && cur[k+2]==0) // 本行,上行的k和k+1,k+2位置均可用
{
cur[k]=cur[k+1]=cur[k+2]=2;
temp=status+b[k]*2+b[k+1]*2+b[k+2]*2;
dfs(i,now+1,k+3,temp);
cur[k]=cur[k+1]=cur[k+2]=0;
} // 放置2行*3列 矩阵
if (k+1<=m) dfs(i,now,k+1,status);
}
int main()
{
int i,Case,k,aim,status,j,x,y;
b[0]=0;
b[1]=1;
for (i=2;i<=11;i++)
b[i]=b[i-1]*3;
scanf("%d",&Case);
while (Case--)
{
scanf("%d%d%d",&n,&m,&k);
memset(map,0,sizeof(map));
while (k--)
{
scanf("%d%d",&x,&y);
map[x][y]=1;
}
aim=b[m+1]-1;
status=0;
for (i=1;i<=m;i++)
if (map[1][i]==1) status+=2*b[i];
else status+=b[i];
memset(dp,-1,sizeof(dp));
dp[1][status]=0;
ans=0;
for (i=2;i<=n;i++)
{
memset(dp[i%2],-1,sizeof(dp[i%2]));
for (j=0;j<=aim;j++)
if (dp[1-i%2][j]!=-1)
{
status=updata(i,j);
dfs(i%2,dp[1-i%2][j],1,status);
}
}
printf("%d\n",ans);
}
return 0;
}