POJ 1014 Dividing ( 多重背包)
2013-08-27 16:06
225 查看
题意:玛莎和比尔有一批大理石(或弹珠)。他们想要将这批大理石分成价值和相等的两批。如果所有的大理石有同样的价值,那很简单,因为只要按数目分一半就行了。但是很可惜,一些大理石大一点,或者更漂亮一点。所以玛莎和比尔对每一个大理石分配一定的价值分从1到6。现在他们要分离这些大理石使得分别能获得相同总值。很可惜,他们意识到有时不可能平分大理石(即使总值是偶数)。例如,如果有1个价值为1,1个价值为3,两个价值为4的大理石,这样他们不可能被平分,因此,他们请求你来写一个程序来判断是否能平分。
分析:
如果想要公平的分得弹球,那么弹球的价值总和一定是偶数,可以先进行判断弹球的价值总和,若是奇数则不需要做下面的判断。
如果是偶数,我们可以把这个问题映射为多重背包问题,并且这个背包是要求完全装满的。背包的总容量V就是所有弹球总价值和sum的一半,弹球的cost和weight都是其编号。个数则是由外界输入的。最后进行判断:如果得到的F[V]确定的等于sum/2,则说明能够公平的分弹球。需要注意的是,由于弹球最大个数是20000,所以极端情况是20000个弹球都是放在了价值为6的位置上。
分析:
如果想要公平的分得弹球,那么弹球的价值总和一定是偶数,可以先进行判断弹球的价值总和,若是奇数则不需要做下面的判断。
如果是偶数,我们可以把这个问题映射为多重背包问题,并且这个背包是要求完全装满的。背包的总容量V就是所有弹球总价值和sum的一半,弹球的cost和weight都是其编号。个数则是由外界输入的。最后进行判断:如果得到的F[V]确定的等于sum/2,则说明能够公平的分弹球。需要注意的是,由于弹球最大个数是20000,所以极端情况是20000个弹球都是放在了价值为6的位置上。
// 380K 16MS #include <stdio.h> #define MAX 60005 #define max(a,b) ((a)>(b)?(a):(b)) int dp[MAX] ; int V ; int num[7] ; void ZeroOnePack ( int const cost , int const value ) { int i ; for ( i = V ; i >= cost ; i -- ) { dp[i] = max( dp[i] , dp[i-cost] + value ) ; } } void CompletePack ( int const cost , int const value ) { int i ; for ( i = cost ; i <= V ; i ++ ) { dp[i] = max ( dp[i] , dp[i-cost] + value ) ; } } void MultiplePack ( int const cost , int const value , int amount ) { if ( amount * cost > V ) { CompletePack ( cost , value ) ; } else { int k ; for ( k = 1 ; k < amount ; k *= 2 ) { ZeroOnePack ( k * cost , k * value ) ; amount -= k ; } if ( amount ) { ZeroOnePack ( amount * cost , amount * value ) ; } } } void Init_DP ( ) { int i ; for ( i = 1 ; i <= V ; i ++ ) { dp[i] = 0 ; } } int main ( ) { int count ; count = 1 ; while ( 1 ) { int sum ; sum = 0 ; int i ; for ( i = 1 ; i <= 6 ; i ++ ) { scanf ("%d" , & num[i] ) ; sum += i * num[i] ; } if ( !sum ) { break ; } else { if ( sum % 2 )//不剪枝铁定WA { printf ("Collection #%d:\nCan't be divided.\n\n", count ) ; } else { V = sum/2 ; for ( i = 1 ; i <= 6 ; i ++ ) { MultiplePack ( i , i , num[i] ) ; } if ( dp[V] == V ) { printf ("Collection #%d:\nCan be divided.\n\n" , count ) ; } else { printf ("Collection #%d:\nCan't be divided.\n\n", count) ; } } } Init_DP ( ) ; count ++ ; } return 0 ; }
相关文章推荐
- POJ 1014 Dividing 多重背包
- HDU1059 && POJ1014 :Dividing(多重背包)
- 【POJ1014】Dividing 多重背包,二进制物品拆分转01背包
- POJ 1014 Dividing (多重背包)
- poj1014 hdu1059 Dividing 多重背包
- Dividing - POJ 1014 dp背包
- POJ_1014 Dividing(多重背包问题)
- hdu1059 &poj1014 Dividing (多重背包)
- poj 1014 Dividing 多重背包 二进制拆分
- POJ1014--多重背包--Dividing
- Hdu 1059 Dividing & Zoj 1149 & poj 1014 Dividing(多重背包)
- POJ 1014 Dividing 多重背包
- poj1014 hdu1059 Dividing 多重背包
- poj 1014 Dividing 【多重背包】
- poj 1014 Dividing 多重背包
- ZOJ1149 POJ1014 HDU1059 Dividing,多重背包问题
- 【多重背包】poj 1014 Dividing
- POJ 1014 Dividing【多重背包+二进制优化】
- POJ 1014 Dividing 多重背包
- POJ 1014 Dividing(多重背包 + 二进制优化 + 01背包)