状压DP问题
2015-08-17 15:00
441 查看
状态压缩·一
题目传送:#1044 : 状态压缩·一AC代码:
[code]#include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <complex> #include <cstdlib> #include <cstring> #include <fstream> #include <sstream> #include <utility> #include <iostream> #include <algorithm> #include <functional> #define LL long long #define INF 0x7fffffff using namespace std; int n, m, q; int w[1005]; int dp[1005][1030];//dp[i][j]表示选到第i个位置时j状态能够取得的最大值 int cnt[1030];//代表每个数的位数上的1的个数 int main() { cnt[0] = 0, cnt[1] = 1; for(int i = 2; i < 1030; i ++) cnt[i] = cnt[i >> 1] + cnt[i & 1]; scanf("%d %d %d", &n, &m, &q); for(int i = 1; i <= n; i ++) { scanf("%d", &w[i]); } int ans = 0; int d = 1 << m; for(int i = 1; i <= n; i ++) { for(int j = 0; j < (1 << m); j ++) { if(cnt[j] <= q) dp[i][j] = max(dp[i-1][j >> 1], dp[i-1][(j >> 1) + (1 << (m - 1))]) + (j & 1) * w[i]; ans = max(ans, dp[i][j]); } } printf("%d\n", ans); return 0; }
Hackers’ Crackdown
题目传送:UVA - 11825 - Hackers’ CrackdownAC代码:
[code]#include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <complex> #include <cstdlib> #include <cstring> #include <fstream> #include <sstream> #include <utility> #include <iostream> #include <algorithm> #include <functional> #define LL long long #define INF 0x7fffffff using namespace std; const int maxn = (1 << 16) + 5; int dp[maxn];//dp[i]表示子集i最多可以分成多少组 int cover[maxn];//cover[i]表示若干集合(i中所表示的集合)的并集 int n, m; int P[25];//P[i]表示与i相连的数的集合(包括i) int main() { int cas = 1; while(scanf("%d", &n) != EOF) { if(n == 0) break; for(int i = 0; i < n; i ++) { scanf("%d", &m); P[i] = 1 << i; int t; while(m --) { scanf("%d", &t); P[i] |= (1 << t);//并入集合i } } for(int i = 0; i < maxn; i ++) { cover[i] = 0; for(int j = 0; j < n; j ++) {//if判断j是否在i中,是得话就并入 if(i & (1 << j)) cover[i] |= P[j]; } } dp[0] = 0; int tot = (1 << n) - 1;//全集总数 for(int i = 1; i <= tot; i ++) {//依次枚举全集,因为要先算出前一状态才能推出后一状态 dp[i] = 0; for(int j = i; j; j = (j - 1) & i) {//枚举子集的技巧,重点! if(cover[j] == tot) {//i的子集j等于全集,则执行状态转移 dp[i] = max(dp[i], dp[i ^ j] + 1); } } } printf("Case %d: %d\n", cas ++, dp[tot]); } return 0; }
Sharing Chocolate
题目传送:UVALive - 4794 - Sharing ChocolateWF2010的题。
AC代码:
[code]#include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <complex> #include <cstdlib> #include <cstring> #include <fstream> #include <sstream> #include <utility> #include <iostream> #include <algorithm> #include <functional> #define LL long long #define INF 0x7fffffff using namespace std; const int maxn = 16; int d[1 << maxn][105]; int vis[1 << maxn][105]; int sum[1 << maxn]; int a[maxn]; int n; int bitcount(int x) { return x == 0 ? 0 : bitcount(x / 2) + (x & 1); } int dp(int s, int x) {//每次递归找出集合为s,宽为x的巧克力是否可以满足要求 if(vis[s][x]) return d[s][x]; vis[s][x] = 1; int& ans = d[s][x]; if(bitcount(s) == 1) return ans = 1;//此时为边界,即只有一块巧克力的情况,肯定是满足的 int y = sum[s] / x;//另一个边长可以根据这个求得 for(int s0 = (s - 1) & s; s0; s0 = (s0 - 1) & s) {//枚举子集 int s1 = s - s0; if(sum[s0] % x == 0 && dp(s0, min(x, sum[s0] / x)) && dp(s1, min(x, sum[s1] / x))) return ans = 1;//竖着切(这里假定宽x是竖着的) if(sum[s0] % y == 0 && dp(s0, min(y, sum[s0] / y)) && dp(s1, min(y, sum[s1] / y))) return ans = 1;//横着切 } return ans = 0; } int main() { int cas = 1, x, y; while(scanf("%d", &n) != EOF) { if(n == 0) break; scanf("%d %d", &x, &y); for(int i = 0; i < n; i ++) scanf("%d", &a[i]); //计算每个子集的元素的和 memset(sum, 0, sizeof(sum)); for(int s = 0; s < (1 << n); s ++) { for(int i = 0; i < n; i ++) if(s & (1 << i)) sum[s] += a[i]; } memset(vis, 0, sizeof(vis)); int ALL = (1 << n) - 1; int ans; if(sum[ALL] != x * y) ans = 0; else ans = dp(ALL, min(x, y)); printf("Case %d: %s\n", cas ++, ans ? "Yes" : "No"); } return 0; }
相关文章推荐
- sobel和laplace算子
- iOS自动检查更新
- 获取spring容器,以访问容器中定义的其他bean
- 当前窗口的高和宽
- oc 类的使用
- java 反射
- Android 开发之 SimpleTagImageView自定义ImageView
- iOS开发系列--地图与定位
- windows下C语言枚举串口端口
- Lowest Bit
- Ubuntu 14.04下SublimeText 3支持中文输入法
- Installing the PHP/MongoDB extension on Mac OSX 10.8
- 序列合并求前K小项 POJ2442
- Knockout.js Style绑定
- 【转】Maven最佳实践:划分模块
- JavaBean对象转map
- 安卓学习笔记(一)自定义控件2
- java代码执行顺序
- HDU 4121 Xiangqi 模拟
- SAP 金税接口介绍