NYOJ 325 zb的生日(搜索解平分问题)
地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=325
题意:
有n个西瓜(n<=20),每个西瓜有一定的重量(w<=10000),将它们分成两堆,问如何使两堆重量之差最小。
解题思路:
还是看成容量为 sum/2 的背包问题,用搜索枚举所有情况,使背包中的重量尽量大。如此可得到最优解。
搜索的效率取决于剪枝。而剪枝一般有两种,可行性剪枝与最优性剪枝。
可行性:如果将物品装入背包后,费用超过容量,则不将它放入背包。
最优性:1、如果背包已经装满,则不再考虑其他情况。
2、如果背包中已有物品加上现有可选物品的总重量都不大于已知的最优解,则剪枝。
1 2 #include <stdio.h> 3 #define max(a,b) a>b?a:b 4 int V,ans,n,w[21],sum[21]; 5 void dfs(int i,int cnt) 6 { 7 if(i == 0) 8 { 9 ans = max(ans,cnt); 10 return ; 11 } 12 if(ans == V || cnt+sum[i] <= ans) //cut 13 return ; 14 if(cnt+w[i] <= V) 15 dfs(i-1,cnt+w[i]); 16 dfs(i-1,cnt); 17 } 18 int main() 19 { 20 while(~scanf("%d",&n)) 21 { 22 ans = 0; 23 for(int i=1;i<=n;i++) 24 { 25 scanf("%d",&w[i]); 26 sum[i] = sum[i-1] + w[i]; 27 } 28 V = sum[n]/2; 29 dfs(n,0); 30 printf("%d\n",sum[n]-2*ans); 31 } 32 return 0; 33 }