首页 > 代码库 > POJ 1038 状压DP
POJ 1038 状压DP
一个公司生产一种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; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。