题目:有一些石头,每块石头有一个价值价值(1~6中的一个整数),现在把石头分成两组,
问能否分成价值和相同的两组。
分析:dp,01背包。背包容量为总和的一半,判断能否放满即可。
说明:数据较大,使用二进制拆分╮(╯▽╰)╭。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int f[60001],c[6],w[6] = {1,2,3,4,5,6}; int p[60001]; int main() { int t = 1; while (scanf("%d%d%d%d%d%d",&c[0],&c[1],&c[2],&c[3],&c[4],&c[5])) { int sum = 0; for (int i = 0 ; i < 6 ; ++ i) sum += c[i]*w[i]; if (sum == 0) break; //二进制拆分 int count = 0; for (int i = 0 ; i < 6 ; ++ i) { int k = 1,cc = c[i]; while (k < cc) { p[count ++] = k*w[i]; cc -= k; k <<= 1; } if (cc) p[count ++] = cc*w[i]; } printf("Collection #%d:\n",t ++); if (sum%2) printf("Can't be divided.\n\n"); else { int m = sum/2; memset(f, 0, sizeof(f)); f[0] = 1; for (int i = 0 ; i < count ; ++ i) for (int v = m ; v >= p[i] ; -- v) if (f[v-p[i]]) f[v] = 1; if (!f[m]) printf("Can't be divided.\n\n"); else printf("Can be divided.\n\n"); } } return 0; }
时间: 2024-11-08 10:07:34