您的位置:首页 > 其它

POJ 1014 Dividing

2012-08-14 09:20 274 查看

Dividing

题目意思很清楚,这里就不再翻译了。初始的时候,我将他当作分组背包(估计是最近做分组背包做的太多了),来解,但一直超时,后来分析了一下时间复杂度为O(v*n),看了一下数据后,发现根本不可能过的去,v最大可有90000,而n最大有20000,这样怎么可能过的去。。。。。。后来看别人的解题报告的时候,发现可以用多重背包。然后我就对比了一下两者的情况。用分组背包的时候是这么考虑的:每类物品中可以选取一件,也可以选取两件。。。。而这些选择之间是互斥的,所以可用分组背包,而用多重背包更没问题。不过这个题目,用多重背包会更快,多重背包的复杂度为:O(v*sum(log
num[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 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: