Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 13321 Accepted Submission(s): 3739
01背包,完全背包,多重背包 ,模板代码:http://blog.csdn.net/deng_hui_long/article/details/10603015
题意:Marsha and Bill 收集了一些弹珠,每个弹珠的价值,都不一样,要求你写一个程序,是否可以平分这个弹珠。
思路: 这是一个多重背包的问题, 求两个人是否可以平分,我们先要求出它的总价值,如果可以平分,说明的两个人的按价值是一样的,即总价值/2,平分给他们呢两个人。
import java.io.*; import java.util.*; /* * * author : denghuilong * Date : 2013-8-30 * */ public class Main { int n = 6; int dp[] = new int[2000000]; int sum; public static void main(String[] args) { new Main().work(); } void work() { Scanner sc = new Scanner(new BufferedInputStream(System.in)); int Case = 1; while (sc.hasNext()) { Node node = new Node(); Arrays.fill(dp, 0); sum = 0; for (int i = 1; i <= n; i++) { node.num[i] = sc.nextInt();//弹珠的数量 node.val[i] = i;//弹珠的价值 sum += (node.num[i] * node.val[i]);//总价值 } if (sum == 0) break; if ((sum & 1) != 0) {//等价于 sum%2 是否等于0,如果不等于0,说明他们不可以平分 System.out.println("Collection #" + Case++ + ":"); System.out.println("Can't be divided."); System.out.println(); } else { sum >>= 1;//右一位,表示除以2, 要求平分即:总价值/2; for (int i = 1; i <= n; i++) { multiplePack(node.val[i], node.val[i], node.num[i]); } System.out.println("Collection #" + Case++ + ":"); if (dp[sum] != sum) System.out.println("Can't be divided."); else System.out.println("Can be divided."); System.out.println(); } } } //多重背包 void multiplePack(int cost, int weight, int amount) { if (cost * amount >= sum) {// 如果大于一半,数量是无限的,按完全背包处理 completePack(cost, weight); } else {//小于一半按01背包处理 int k = 1; while (k < amount) { ZeroOnePack(k * cost, k * weight); amount -= k; k <<= 1; } ZeroOnePack(amount * cost, amount * weight); } } //01背包 void ZeroOnePack(int cost, int weight) { for (int i = sum; i >= cost; i--) { dp[i] = Math.max(dp[i], dp[i - cost] + weight); } } // 完全背包 void completePack(int cost, int weight) { for (int i = cost; i <= sum; i++) { dp[i] = Math.max(dp[i], dp[i - cost] + weight); } } class Node { int num[] = new int[n + 1]; int val[] = new int[n + 1]; } }