sgu138状压dp用dfs来统计
来源:互联网 发布:玉帝 天帝知乎 编辑:程序博客网 时间:2024/05/16 15:15
题目大意:有一个大小为N * M的蛋糕,蛋糕上面有k根蜡烛,现在要求你在蛋糕上面铺1 * 2和2 * 1的巧克力
使得所铺的巧克力最少,且蛋糕上面没有空余地方可放巧克力了(只存在1 * 1的没铺的方格)
解题思路:1 * 1的空闲方格由三行决定,上一行,当前行和下一行,如果只考虑两行的话,就比较难了
所以我们用dp[i][s1][s2]表示第i行的状态是s1,第i + 1行的状态是s2的情况下放的最少巧克力数量
如此的话,可得到递推方程
dp[i][s1][s2] = min(dp[i][s1][s2], dp[i-1][s3][s4] + cnt)
解释上面方程的意思:在第i-1行的状态是s3,第i行的状态是s4的情况下,在第i行和第i+1上铺巧克力,使第i行的状态变成s1,第i+1行的状态变成s2,统计出铺在第i行和第i+1行的巧克力数量cnt,这样的话,状态转移就完成了
现在的问题是如何更新,更新第i行的话有可能有影响到第i+1行,所以传入两个状态,第i行和第i+1行的状态,然后dfs暴力枚举出放的巧克力,统计一下即可
这里在更新第N行的时候,需要用到第N+1行,又因为第N+1行是外界的行,所以最后的答案是
min(dp[N][s1][0]),第N+1行不能被占用,如果被占用,就表示放的巧克力超出边界了
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;int n, m;char str[75][10];int dp[2][130][130];int s[75];int tmpps, tmpns, pre, now;void dfs(int ps, int ns, int nts, int ni, int cnt) { if (ni > 0 && ((ps>>(ni - 1))&1) == 0 && ((ns>>(ni - 1))&1) == 0) return;//检测i-1行与i行是不是满足题意,横着放或者竖着放 if (ni > 1 && ((ns>>(ni - 1))&1) == 0 && ((ns>>(ni - 2))&1) == 0) return;//如果不满足就直接退出就好了 if (ni == m) { dp[pre^1][ns][nts] = min(dp[pre^1][ns][nts], dp[pre][tmpps][tmpns] + cnt); return; } dfs(ps, ns, nts, ni + 1, cnt);//如果第i-1行与第i行配合就已经把第i行的ni位置搞定了就接着往下搜,而不必使用第i+1行了。 //这两个是如果上面所说的情况不符合,那么就要用到i+1行了,横着放和竖着放两种情况,然后在往下搜索。 if (ni < m - 1 && ((ns>>ni)&1) == 0 && ((ns>>(ni + 1))&1) == 0) dfs(ps, ns|(1<<ni)|(1<<(ni + 1)), nts, ni + 2, cnt + 1); if (((ns>>ni)&1) == 0 && ((nts>>ni)&1) == 0) dfs(ps, ns|(1<<ni), nts|(1<<ni), ni + 1, cnt + 1);}int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%s", str[i]); for (int j = 0; j < m; j++) if (str[i][j] == '*') s[i] |= (1<<j); } int ss = (1<<m); pre = 0, now = 1; for (int i = 0; i < ss; i++) for (int j = 0; j < ss; j++) dp[now][i][j] = INF; dp[now][ss - 1][s[1]] = 0; for (int k = 1; k <= n; k++) { swap(now, pre); for (int i = 0; i < ss; i++) for (int j = 0; j < ss; j++) dp[now][i][j] = INF; for (int i = 0; i < ss; i++) { if (i&s[k - 1] != s[k - 1]) continue;//i中可以包含s,也就是说s是0的位置,i中可以是1 for (int j = 0; j < ss; j++) { if (j&s[k] != s[k]) continue;//这个也是同理 if (dp[pre][i][j] == INF) continue;//第i-1行还能放,就直接跳过 tmpps = i; tmpns = j;//记录现在枚举的这两个状态 dfs(i, j, s[k + 1], 0, 0); } } } int ans = INF; for (int i = 0; i < ss; i++) ans = min(ans, dp[now][i][0]); printf("%d\n", ans); return 0;}
0 0
- sgu138状压dp用dfs来统计
- POJ2411,dp+dfs+状压
- POJ 2411 状压DP&&DFS
- DP问题用dfs实现
- DFS+DP
- 【状压DP】【cofun1895】队伍统计
- sgu138:Games of Chess
- SGU138 Games of Chess
- sgu138: Games of Chess
- POJ1321 棋盘问题(DFS||状压DP)
- poj2411--Mondriaan's Dream(状压dp+dfs)
- POJ1321:棋盘问题(状压dp & DFS)
- 用jfreechart来生成统计图表
- 用jfreechart来生成统计图表
- 用Eclipse来统计代码行数
- 用Eclipse来统计代码的行数
- 用accumulate或for_each来统计区间
- HDU1078(树形DP+DFS)
- 学习hadoop(1)年底最高温度统计
- 提高iOS开发效率
- ThinkPHP3.2.3配置UEditor。
- http连接之HttpClient
- 转载:HttpURLConnection用法详解
- sgu138状压dp用dfs来统计
- VMware Workstation虚拟机linux操作系统添加硬盘(Centos5.5)的简单教程
- coj 1018: Avatar
- Mac下删除安装的pkg
- 使用XeLaTex输出中文
- JAVA大整数[小结]
- UIPageControl 与 UIScrollView
- Delphi XE5使用GPIP读取图片长宽和分辨率
- LeetCode之Construct Binary Tree from Inorder and Postorder Traversal