状态压缩DP——POJ 2923
来源:互联网 发布:民国报刊数据库 编辑:程序博客网 时间:2024/06/07 02:37
对应POJ题目:点击打开链接
题意:有n件家具和两辆车(容量分别为c1, c2),某人要搬家,问至少需要几次才能把所有家具运完(两辆车必须同时行驶)。
思路:
n很小,可以用二进制保存1 ~ (1<<n) - 1 种状态,每种状态表示几件家具,比如n = 7时。5这个状态,5用二进制表示为 0000101,可以用它表示为第5件家具和第7件家具被选上(或者从右边数起,表示第1和第3件家具)。之后可以枚举每种状态i,之后用两个循环就可完成。转移方程为:dp[i | j] = min{dp[i | j], dp[i] + 1}; (j表示j状态能否一次被两辆车运走,其中i & j 要为空)。dp[x] 表示x状态至少需要几次才能拉走,所以dp[(1<<n) - 1] 就是答案。
再来看怎样求一个状态x,使它能一次被两辆车运走 。先根据状态x的二进制中为1的位置进行对应家具求和sum,然后枚举x的子状态,同样据子状态的二进制中为1的位置进行对应家具求和sum1(表示此sum1要被两辆车中的某辆一次拉走),sum2 = sum - sum1。如果sum1和sum2都符合载重。则状态x能一次被两辆车运走。
#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 10#define M (1<<N)#define INF (1<<30)#define MIN(x, y) ((x) < (y) ? (x) : (y))#define SIZE ((1<<n)-1)int a[N];int dp[M];int OK[M];int c1, c2;bool Judge(int x){int i, j, t = 0;int sum1 = 0, sum2 = 0, sum = 0;for(i=1; i<=x; i=(1<<t)){ /* 对x集合所包含的物品求和 */if(i & x) sum += a[t];t++;}if(sum > c1 + c2) return 0;for(i=1; i<=x; i++){ /* 枚举x的子集 */if((i & x) != i) continue; /* i不是x的子集 */sum1 = t = 0;for(j=1; j<=i; j=(1<<t)){if(j & i) sum1 += a[t];t++;}sum2 = sum - sum1;if(sum1 <= c1 && sum2 <= c2) return 1;if(sum2 <= c1 && sum1 <= c2) return 1;}return 0;}int main(){//freopen("in.txt", "r", stdin);int T, n, w = 0;int i, j, ans;scanf("%d", &T);while(T--){memset(OK, 0, sizeof(OK));scanf("%d%d%d", &n, &c1, &c2);for(i=0; i<n; i++) scanf("%d", a + i);for(i=1; i<M; i++) dp[i] = INF;for(i=1; i<=SIZE; i++)if(Judge(i)) OK[i] = dp[i] = 1;for(i=1; i<=SIZE; i++){for(j=1; j<=SIZE; j++){if(i & j) continue; /* 交集不为空 */if(dp[i] != INF && OK[j])dp[i|j] = MIN(dp[i|j], dp[i] + 1);}}printf("Scenario #%d:\n%d\n", ++w, dp[SIZE]);if(T) printf("\n");}return 0;}
0 0
- 状态压缩DP——POJ 2923
- POJ 2923(dp + 状态压缩)
- poj 2923 状态压缩dp
- POJ 2923 Relocation / 状态压缩DP
- POJ 2923-Relocation-状态压缩+DP
- POJ 3254 Corn Fields——状态压缩dp
- 【状态压缩DP】POJ 1170
- 【状态压缩DP】POJ 1185
- POJ 3254 状态压缩DP
- poj 3254 状态压缩dp
- poj 3254 状态压缩DP
- poj 1185(状态压缩dp)
- poj 3254(状态压缩dp)
- poj 3311(状态压缩dp)
- poj-2411-状态压缩DP
- POJ 3254 状态压缩DP
- Poj 2404 状态压缩DP
- poj 2411 状态压缩dp
- 显示脸上的关键点的程序
- LeetCode_Plus One
- 【蓝桥杯题目分析】2014年第五届——第一题:啤酒和饮料
- 如何判断对象类型/对typeof方法使用认识
- C++引用二常引用:
- 状态压缩DP——POJ 2923
- Java NullPointerException原因知多少
- 百度贴吧爬虫【练手】
- AT&T汇编语言语法
- Hadoopo——删除文件
- 详解JNDI的lookup资源引用 java:/comp/env
- 5.6.3 super限定
- 黑马程序员——小白入门之Java概述
- SharePoint 2013的限制(二)网站集和列表/文档库