首页 > 代码库 > ZOJ 3777 Problem Arrangement(状压DP)
ZOJ 3777 Problem Arrangement(状压DP)
题目链接 : http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5264
//今年省赛的题目,比赛的时候知道是状压却一直没搞出,直到最后。虽然赛后知道做法,也一直没做的,最近想不开就来做了 - -, 顺便用了下快速枚举k-子集。
恩, 做法么就是开dp[i][j] i已经选过了的题目的一个集合,j表示的是获得了j分,然后就可以直接做了。。(但是好像说会T或者卡空间,我的做法是快速枚举k-子集,这个东西可以看下watashi翻译的《挑战编程竞赛》的p157。。 汗
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 //#include <cmath> 6 7 using namespace std; 8 9 int P[15][15];10 int dp[1<<12][505];11 int n, m;12 13 int main() {14 int T;15 scanf("%d", &T);16 for (int cas = 1; cas <= T; cas++) {17 scanf("%d%d", &n, &m);18 for (int i = 1; i <= n; i++) {19 for (int j = 1; j <= n; j++) scanf("%d", &P[i][j]);20 }21 memset(dp, 0, sizeof(dp)); dp[0][0] = 1;22 23 for (int k = 1; k <= n; k++) {24 int comb = (1 << k) - 1;25 while (comb < (1 << n)) {26 for (int i = 0; i < n; i++) {27 if (comb >> i & 1) {28 int add = P[i + 1][k], low = max(0, m-add);29 for (int j = m; j >= low; j--) dp[comb][m] += dp[comb-(1<<i)][j];30 for (int j = low - 1; j >= 0; j--) dp[comb][j+add] += dp[comb-(1<<i)][j];31 }32 }33 int x = comb & -comb, y = comb + x;34 comb = ((comb & ~y) / x >> 1) | y;35 }36 }37 int ret = dp[(1<<n)-1][m];38 if (!ret) puts("No solution");39 else {40 int nex = 1;41 for (int i = 1; i <= n; i++) nex *= i;42 int d = __gcd(ret, nex);43 printf("%d/%d\n", nex/d, ret/d);44 }45 }46 return 0;47 }
ZOJ 3777 Problem Arrangement(状压DP)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。