1014 Dividing dp/dfs

Posted sweet-ginger-candy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1014 Dividing dp/dfs相关的知识,希望对你有一定的参考价值。

先用dfs方法:(注意剪枝的重要性)

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int sumvalue,halfvalue;
int n[7];
bool flag;//记录是否能够进行平分。
void dfs(int value,int c)
    if(flag)
        return;
    if(value==halfvalue)
        flag=true;
        return;
    
    for(int i=c;i>=1;i--)
        if(n[i])
            if(value+i<=halfvalue)//注意<=号的意义
                n[i]--;
                dfs(value+i,i);
                if(flag)
                    break;
            
        
    
    return ;

int main()
    int k=0;
    while(true)
        sumvalue=0;//注意sumvalue初始化的位置,而且必须进行初始化。
        k++;
    for(int i=1;i<=6;i++)
        cin>>n[i];
        sumvalue+=(i*n[i]);
    
    if(sumvalue==0)
        break;
    if(sumvalue%2!=0)//为真
        cout<<"Collection #"<<k<<":"<<endl;
        cout<<"Can‘t be divided."<<endl;
        cout<<endl;
        continue;
    
    halfvalue=sumvalue/2;
    flag=false;//为了验证dfs的效果。
    dfs(0,6);
    if(flag)
        cout<<"Collection #"<<k<<:<<endl;
        cout<<"Can be divided."<<endl<<endl;
        continue;
        
    else
        cout<<"Collection #"<<k<<:<<endl;
        cout<<"Can‘t be divided."<<endl<<endl;
        continue;
        
    
    return 0;

多重背包+二进制优化

来源:https://blog.csdn.net/lyy289065406/article/details/6661449

#include<iostream>
using namespace std;
 
int n[7];  //价值为i的物品的个数
int v;  //背包容量
int SumValue;  //物品总价值
bool flag;    //标记是否能平分SumValue
int dp[100000];  //状态数组
 
int max(int a,int b)

    return a>b?a:b;

 
/*完全背包*/
void CompletePack(int cost,int weight)

    for(int i=cost;i<=v;i++)
    
        dp[i]=max(dp[i],dp[i-cost]+weight);
        if(dp[i]==v)    //剪枝,当能够平分SumValue时退出
        
            flag=true;
            return;
        
    
            
    return;

 
/*01背包*/
void ZeroOnePack(int cost,int weight)

    for(int i=v;i>=cost;i--)
    
        dp[i]=max(dp[i],dp[i-cost]+weight);
        if(dp[i]==v)    //剪枝
        
            flag=true;
            return;
        
    
    return;

 
/*多重背包*/
void MultiplePack(int cost,int weight,int amount)

    if(cost*amount>=v)
    
        CompletePack(cost,weight);
        return;
    
 
    if(flag)    //剪枝
        return;
 
    /*二进制优化*/
    int k=1;
    while(k<amount)
    
        ZeroOnePack(k*cost,k*weight);
 
        if(flag)    //剪枝
            return;
 
        amount-=k;
        k*=2;
    
    ZeroOnePack(amount*cost,amount*weight);
 
    return;

 
int main(int i)

    int test=1;
    while(cin>>n[1]>>n[2]>>n[3]>>n[4]>>n[5]>>n[6])
    
        SumValue=0;  //物品总价值
 
        for(i=1;i<=6;i++)
            SumValue+=i*n[i];
 
        if(SumValue==0)
            break;
 
        if(SumValue%2)    //sum为奇数,无法平分
        
            cout<<"Collection #"<<test++<<:<<endl;
            cout<<"Can‘t be divided."<<endl<<endl;    //注意有空行
            continue;
        
 
        v=SumValue/2;
        memset(dp,-1,sizeof(dp));
        dp[0]=0;
        flag=false;
 
        for(i=1;i<=6;i++)
        
            MultiplePack(i,i,n[i]);
 
            if(flag)    //剪枝
                break;
        
 
        if(flag)
        
            cout<<"Collection #"<<test++<<:<<endl;
            cout<<"Can be divided."<<endl<<endl;
            continue;
        
        else
        
            cout<<"Collection #"<<test++<<:<<endl;
            cout<<"Can‘t be divided."<<endl<<endl;
            continue;
        
    
    return 0;

 

以上是关于1014 Dividing dp/dfs的主要内容,如果未能解决你的问题,请参考以下文章

poj 1014 Dividing

POJ-1014 Dividing

AC日记——Dividing poj 1014

POJ 1014: Dividing

多重背包,附上例题(POJ - 1014 Dividing)

POJ1014Dividing[多重背包可行性]