POJ 1014 Dividing
2012-08-14 09:20
274 查看
Dividing
题目意思很清楚,这里就不再翻译了。初始的时候,我将他当作分组背包(估计是最近做分组背包做的太多了),来解,但一直超时,后来分析了一下时间复杂度为O(v*n),看了一下数据后,发现根本不可能过的去,v最大可有90000,而n最大有20000,这样怎么可能过的去。。。。。。后来看别人的解题报告的时候,发现可以用多重背包。然后我就对比了一下两者的情况。用分组背包的时候是这么考虑的:每类物品中可以选取一件,也可以选取两件。。。。而这些选择之间是互斥的,所以可用分组背包,而用多重背包更没问题。不过这个题目,用多重背包会更快,多重背包的复杂度为:O(v*sum(lognum[i])),所以,直接按照模版写就可以过了。
#include <stdio.h> #include <string.h> int num[10] ; int sum ; int dp[100000] ; int tag ; #define INF -100000000 bool read(){ bool flag = 0 ; sum = 0 ; for(int i = 1 ; i <= 6 ; i ++){ scanf("%d" , &num[i]) ; sum += num[i] * i ; if(num[i]) flag = 1 ; } return flag ; } inline int max(int a , int b){ return a > b ? a : b ; } void ZeroOnePack(int cost , int weight){ for(int v = sum/2 ; v >= cost ; v--){ dp[v] = max(dp[v] , dp[v-cost] + weight) ; if(dp[v]==sum/2){ tag = 1 ; return ; } } } void CompletePack(int cost , int weight){ for(int v = cost ; v <= sum/2 ; v ++){ dp[v] = max(dp[v] , dp[v-cost] + weight) ; if(dp[v]== sum/2){ tag = 1 ; return ; } } } void MultiplePack(int cost ,int weight ,int amount){ if(cost * amount >= sum/2){ CompletePack(cost , weight) ; return ; } int k(1) ; while(k < amount){ ZeroOnePack(k * cost , k * weight) ; if(tag) return ; amount = amount - k ; k = k * 2 ; } ZeroOnePack(amount * cost , amount * weight) ; return ; } void solve(){ //init if(sum%2){ printf("Can't be divided.\n"); return ; } tag = 0 ; for(int i = 1 ; i <= sum/2 ; i ++) dp[i] = INF ; for(int i = 1 ; i <= 6 ; i ++){ MultiplePack(i , i , num[i]) ; if(tag) break ; } if(tag){ printf("Can be divided.\n") ; } else{ printf("Can't be divided.\n") ; } } int main(){ int t(0) ; while(read()){ printf("Collection #%d:\n" , ++t) ; solve() ; printf("\n") ; } return 0 ; }
然而这个题目也可以有其他的解法:直接搜索,不过需要注意剪枝。
#include <stdio.h> #include <string.h> int num[10] ; int sum ; int tag ; bool read(){ bool flag = 0 ; sum = 0 ; for(int i = 1 ; i <= 6 ; i ++){ scanf("%d" , &num[i]) ; if(num[i]) flag = 1 ; sum += i * num[i] ; } return flag ; } void dfs(int c , int v){ if(v==sum / 2){ tag = 1 ; return ; } if(tag) return ; for(int i = c ; i >= 1 ; i --){ if(num[i]){ if(v + i <= sum / 2){ num[i] -- ; dfs(c , v + i) ; if(tag) return ; } } } return ; } void solve(){ tag = 0 ; if(sum%2){ printf("Can't be divided.\n") ; return ; } dfs(6 , 0) ; if(tag){ printf("Can be divided.\n") ; } else{ printf("Can't be divided.\n") ; } } int main(){ int t(0) ; while(read()){ printf("Collection #%d:\n" , ++t) ; solve() ; printf("\n") ; } return 0 ; }
相关文章推荐
- POJ 1014 Dividing 解答
- POJ 1014 Dividing 解答
- ZOJ 1149 || POJ 1014 || HDU 1059 Dividing
- poj 1014 && zoj 1149 Dividing --- dfs剪枝
- Poj 1014 Dividing//多重背包
- POJ 1014 Dividing(DFS、完全背包、母函数)
- hdu1059 &poj1014 Dividing (多重背包)
- POJ - 1014 - Dividing
- poj 1014 Dividing
- POJ 1014 Dividing 背包
- POJ 1014 Dividing
- POJ-1014-Dividing
- HDU1059 && POJ1014 :Dividing(多重背包)
- POJ1014 Dividing
- POJ_1014 Dividing解题报告
- POJ 1014 Dividing 解答
- POJ 1014 Dividing 解答
- poj - 1014 - Dividing(多重背包)
- POJ 1014 Dividing
- HDOJ 1059 && POJ 1014 Dividing