一、题目大意
有价值为1,2,3,4,5,6的六种大理石,它的数量不一。要在不破坏大理石的情况下,使两人能分到总价值相等的大理石。数量由标准输入给出,问给定数据能否平分。
二、题解
首先,我们要的是平分总价值为两份,这里有一个很明显的剪枝,即如果总价值为奇数则直接输出不可分。如果总价值为偶数,则要把它分为两份,也就是意味着我们要能从给定数量的大理石中选取若干使它的价值为总价值的一半,这样剩下的就是另一半了。这不就是多重背包嘛!
对于多重背包,就是有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。本题求的是价值总和能否等于总价值的一半,如果等于则说明可以分。所以,我们的最大容量就是总价值的一半。还有本题的大理石只有数量和重量两种属性,其实先前提到的大理石的价值就可以看成是重量。这题的做法和之前做的题目是一样的做法,Poj 1742 Coins(多重背包)。
我还是要吐槽一下的,这个题目WA了四次,害的我总在找背包的原因,最后发现误会它了。是哪个该死的break的原因,在判断总价值奇数后就break了,应该是continue才对。这种小失误真是要命啊,要不是怎么说难题最多WA3次,水题就说不准了。
三、java代码
import java.util.Scanner; public class Main{ public static void main(String args[]){ int i, j, sum1, sum2; int n=0; int[] c=new int[7]; //记录大理石个数 Scanner sc=new Scanner(System.in); while(sc.hasNext()){ sum1=0; sum2=0; for(i=1;i<=6;i++){ c[i]=sc.nextInt(); sum2+=c[i]* i; sum1+=c[i]; } if(sum1==0) break; n++; if(sum2 % 2!=0){ //如果总价值为奇数则不可分 System.out.println("Collection #"+n+":"); System.out.println("Can't be divided."); System.out.println(); continue; //注意用continue } boolean dp[]=new boolean[sum2/2+1]; dp[0]=true; for (i=1; i<=6; i++){ if(c[i]!=0){ int num[]=new int[sum2/2+1]; for (j=i; j<=sum2 /2; j++){ if (!dp[j] && dp[j-i] && num[j-i]< c[i]){ dp[j]=true; num[j]=num[j-i]+1; } } } } System.out.println("Collection #"+n+":"); if(dp[sum2/2]){ System.out.println("Can be divided."); }else System.out.println("Can't be divided."); System.out.println(); } } }
版权声明:本文为博主原创文章,未经博主允许不得转载。