poj 1014 硬币分割
来源:互联网 发布:surface rt安装linux 编辑:程序博客网 时间:2024/05/21 17:05
/** poj 1014 经典多重背包问题 by baiwenlei** 题目大意: 给出一些价值在1~6范围间的弹珠,判断是否能够按照价值等分** 解题思路: 多重背包问题,不过本题中若价值不是偶数,直接返回即可** 最后注意输出的时候要求CASE之间有一个空行,最后一个CASE结束以后不空行。否则presentation error. 我就贡献了一个…… * 最后贡献个数据:* 92 84 76 104 86 131* 32 24 16 14 2 1* 0 0 0 0 0 0* 这个数据是按照我的那个理论设计的。 两个都是CAN。**/#include <iostream>namespace { using namespace std; const int VALUE_MAX = 6; int marble_table[VALUE_MAX+1]; const int MARBLE_NUM_MAX = 20000; bool reachable[VALUE_MAX*MARBLE_NUM_MAX/2 + 1]; // 最多20000个弹珠,等分值除以2 inline void zero_one(int V, int v) { for (int i=V; i>=v; --i) { if (!reachable[i]) { reachable[i] = reachable[i-v]; } } } inline void complete(int V, int v) { for (int i=v; i<=V; ++i) { if (!reachable[i]) { reachable[i] = reachable[i-v]; } } } inline void multiple(int V, int v, int n) { if (n*v >= V) { complete(V, v); return; } int r = n; for (int k=1; k<r; k*=2) { zero_one(V, k*v); r -= k; } zero_one(V, r*v); } bool could_split_fairly(int value) { if (value & 1) { return false; } int half_value = (value >> 1); for (int i=0; i<=half_value; i++) { reachable[i] = false; } reachable[0] = true; for (int i=1; i<=VALUE_MAX; i++ ) { int count = marble_table[i]; if (count==0) continue; multiple(half_value, i, count); } return reachable[half_value]; }}int main(){ int n = 0; while (true) { ++n; int sum = 0; for (int i=1; i<=VALUE_MAX; i++) { cin >> marble_table[i]; sum += (marble_table[i] * i); } if (sum == 0) break; // 退出条件 cout << "Collection #" << n << ":" << endl; cout << (could_split_fairly(sum) ? "Can be divided." : "Can't be divided.") << endl << endl; } return 0;}