zoukankan      html  css  js  c++  java
  • poj 1014 Dividing

    Description﹡﹡﹡﹡

    Marsha and Bill own a collection of marbles. They want to split the collection among themselves so that both receive an equal share of the marbles. This would be easy if all the marbles had the same value, because then they could just split the collection in half. But unfortunately, some of the marbles are larger, or more beautiful than others. So, Marsha and Bill start by assigning a value, a natural number between one and six, to each marble. Now they want to divide the marbles so that each of them gets the same total value. Unfortunately, they realize that it might be impossible to divide the marbles in this way (even if the total value of all marbles is even). For example, if there are one marble of value 1, one of value 3 and two of value 4, then they cannot be split into sets of equal value. So, they ask you to write a program that checks whether there is a fair partition of the marbles.

    Input

    Each line in the input file describes one collection of marbles to be divided. The lines contain six non-negative integers n1 , . . . , n6 , where ni is the number of marbles of value i. So, the example from above would be described by the input-line "1 0 1 2 0 0". The maximum total number of marbles will be 20000. 
    The last line of the input file will be "0 0 0 0 0 0"; do not process this line.

    Output

    For each collection, output "Collection #k:", where k is the number of the test case, and then either "Can be divided." or "Can't be divided.". 
    Output a blank line after each test case.

    Sample Input

    1 0 1 2 0 0 
    1 0 0 0 1 1 
    0 0 0 0 0 0 

    Sample Output

    Collection #1:
    Can't be divided.
    
    Collection #2:
    Can be divided.




    很有意义的一道DP题,dd大牛的背包九讲算是认真复习了一遍。
    如果本题不是多组数据的话,用简单的多重背包就行了,所以这题就要优化了。

    首先,多重背包客转化为 0/1背包问题,就是将多个相同的物品看成独立的个体,就可以套用 0/1背包了。
    但如果仅仅这样的话,一定会超时,所以有了个优化————把n个相同的物品拆分成{1,2,4,8,...,2^k,n-2^k+1}个不同的子集,可以证明这些子集可以任意组合成0~~n范围内的任意数,更重要的是,这种拆分方法是分的最少的,优化了算法时间复杂度。
    还有一个优化,当一类物品的总花费大于背包最大容量时,可以转换为完全背包问题,因为即使将将这类物品填满背包,也装不完。

    #include<iostream>
    //#include<fstream> 
    #include<string.h> 
    using namespace std;
    //ifstream fin("cin.in"); 
    
    int f[100001],a[7],ans;bool p=0,flag; 
    
    void CompleteDp(int cost,int value){
         for(int i=cost;i<=ans;i++)
         {
          f[i]=max(f[i],f[i-cost]+value);
          if(f[i]==ans)
          {flag=1;return ;} 
                 } 
         } 
    
    void ZerooneDp(int cost,int value){
         for(int i=ans;i>=cost;i--)
         {
          f[i]=max(f[i],f[i-cost]+value);
          if(f[i]==ans)
          {flag=1;return ;} 
                 } 
         } 
    
    void MixDp(int cost,int value,int num){
         if(cost*num>=ans)
         {
          CompleteDp(cost,value);
          return ; 
                          } 
         int k=1;
         while(k<=num)
         {
          ZerooneDp(k*cost,k*value); 
          if(flag) return ;  
          num-=k;
          k*=2;    
                     } 
         ZerooneDp(num*cost,num*value); 
         return ;
         } 
    
    int main()
    {
        int k=0; 
        while(!cin.eof())
        {
         flag=0;++k;ans=0; 
         memset(f,-1,sizeof(f)); 
         f[0]=0; 
    
         for(int i=1;i<=6;++i)
         cin>>a[i],ans+=i*a[i];
         
         if(ans==0) return 0; 
         
         if(ans%2) 
         {
          if(p==1) cout<<endl;p=1; 
          cout<<"Collection #"<<k<<":"<<endl; 
          cout<<"Can't be divided."<<endl; continue; 
                        } 
                        
         ans/=2; 
         
         for(int i=1;i<=6;i++)
         {    
          MixDp(i,i,a[i]);
          if(flag)  break;       
                 }              
                
         if(flag) 
         {
          if(p==1) cout<<endl;p=1; 
          cout<<"Collection #"<<k<<":"<<endl; 
          cout<<"Can be divided."<<endl; 
                                    } 
         else 
         {
          if(p==1) cout<<endl;p=1; 
          cout<<"Collection #"<<k<<":"<<endl; 
          cout<<"Can't be divided."<<endl; 
    
              } 
                       }   
      //   system("pause"); 
      
        } 
  • 相关阅读:
    [LeetCode] 1131. Maximum of Absolute Value Expression 绝对值表达式的最大值
    [LeetCode] 1130. Minimum Cost Tree From Leaf Values 叶值的最小代价生成树
    [LeetCode] 1129. Shortest Path with Alternating Colors 颜色交替的最短路径
    [LeetCode] 1128. Number of Equivalent Domino Pairs 等价多米诺骨牌对的数量
    [LeetCode] 1125. Smallest Sufficient Team 最小的必要团队
    [LeetCode] 1124. Longest Well-Performing Interval 表现良好的最长时间段
    [LeetCode] 1122. Relative Sort Array 数组的相对排序
    Gitalk 自动初始化评论
    [LeetCode] 1111. Maximum Nesting Depth of Two Valid Parentheses Strings 有效括号的嵌套深度
    [LeetCode] 1110. Delete Nodes And Return Forest 删点成林
  • 原文地址:https://www.cnblogs.com/noip/p/2554142.html
Copyright © 2011-2022 走看看