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"); 
      
        } 
  • 相关阅读:
    第90章、广播之一收听系统广播(从零开始学Android)
    第105章、蓝牙(从零开始学Android)
    实现自定义view(2):仿Android QQ多屏幕显示ListView的效果
    实现自定义view(1):可在全屏幕自由拖动的view
    Android异步处理四:AsyncTask的实现原理
    Android异步处理三:Handler+Looper+MessageQueue深入详解
    Android异步处理二:使用AsyncTask异步更新UI界面
    实体之间的关系主要有以下两种
    hibernate实体对象的三种状态?
    Session提供了两种方法加载数据,区别是什么?
  • 原文地址:https://www.cnblogs.com/noip/p/2554142.html
Copyright © 2011-2022 走看看