zoukankan      html  css  js  c++  java
  • HDU

    题目:

    有两个小朋友想要平分一大堆糖果,但他们不知道如何平分需要你的帮助,由于没有spj我们只需回答能否平分即可。

    糖果大小有6种分别是1、2、3、4、5、6,每种若干颗,现在需要知道能不能将这些糖果分成等额的两堆。

    一颗大小为6的糖果,可以相当于2颗大小为3的糖果,其他同理,即大小满足加法,但是1颗糖果是不能被拆分的。

    Input

    多组输入,每行输入6个非负整数,分别表示大小为1、2、3、4、5、6的糖果的数量,若输入6个0代表输入结束。

    单种糖果的数量不会超过20000。

    Output

    每组询问先输出一行 "Collection #k:",k表示第几组询问。

    再输出一行表示答案,若能分割,输出 “Can be divided.”,若不能输出 ”Can't be divided.“

    每组输出后空一行

    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套一下模板就可以了

    首先求一下所有糖果的总价值sum

    如果sum不是一个偶数,那就直接输出(糖果总价值都是奇数,那就肯定不可能平分)

    Can't be divided.

    每一个糖果有一个价值,这些糖果还有数量,那么就把糖果的价值看成重量,,,对背包总容量sum/2跑一遍多重背包dp

    我们只需要最后的结果dp[sum/2]==sum/2那么就输出

    Can be divided.

    因为我们把糖果的价值看成了容量,那么dp[sum/2]就相当于容量为sum/2的背包能获得的最大价值,如果dp[sum/2]==sum/2,那么也就说明了可以用一些糖果来装满容量为sum/2的背包

    dp数组开多大?因为每种糖果最多20000,那么6*20000=120000,我们开1000000肯定够用

    代码1(交的G++):

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 int dp[1000000],a[20],sum;
     6 void DP(int cost,int num)
     7 {
     8     int i;
     9     if(cost*num>=sum)  //完全背包模板
    10     {
    11         //如果cost*num大于sum的话,那也就相当于完全背包了
    12         for(i=cost;i<=sum;i++)
    13         dp[i]=max(dp[i],dp[i-cost]+cost);
    14         return ;
    15     }
    16 
    17     //下面代码是二进制枚举
    18     int k=1;
    19     while(k<num)
    20     {
    21         for(i=sum;i>=k*cost;i--)
    22         dp[i]=max(dp[i],dp[i-cost*k]+cost*k);
    23         num-=k;
    24         k*=2;
    25     }
    26     //如果二进制枚举后还有剩余,那就把剩下的当为一个整体,用01背包模板枚举
    27     for(i=sum;i>=num*cost;i--)
    28     dp[i]=max(dp[i],dp[i-cost*num]+cost*num);
    29 }
    30 int main(void)
    31 {
    32     int pt=1,i,j;
    33     while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6])
    34     {
    35         if(!a[1]&&!a[2]&&!a[3]&&!a[4]&&!a[5]&&!a[6]) break;
    36         sum=0;
    37         for(i=1;i<=6;i++) sum+=a[i]*i;
    38         printf("Collection #%d:
    ",pt++);
    39         if(sum%2)
    40         {
    41             printf("Can't be divided.
    
    ");
    42             continue;
    43         }
    44         sum/=2;
    45         memset(dp,0,sizeof(dp));
    46         for(i=1;i<=6;i++)  //这个for循环相当于枚举物品
    47             DP(i,a[i]);
    48         if(dp[sum]==sum) printf("Can be divided.
    
    ");
    49         else printf("Can't be divided.
    
    ");
    50     }
    51     return 0;
    52 }
    View Code

    代码2:

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 struct shudui
     6 {
     7     int c,p;
     8 }rice[10];
     9 int dp[1000000];
    10 int main()
    11 {
    12     int a,b,c,d,e,cnt=0;
    13     rice[1].p=1;
    14     rice[2].p=2;
    15     rice[3].p=3;
    16     rice[4].p=4;
    17     rice[5].p=5;
    18     rice[6].p=6;
    19     while(~scanf("%d%d%d%d%d%d",&rice[1].c,&rice[2].c,&rice[3].c,&rice[4].c,&rice[5].c,&rice[6].c))
    20     {
    21         int sum=rice[1].c+rice[2].c*2+rice[3].c*3+rice[4].c*4+rice[5].c*5+rice[6].c*6;
    22         if(rice[1].c==0 && rice[2].c==0 && rice[3].c==0 && rice[4].c==0 && rice[5].c==0 && rice[6].c==0) return 0;
    23         printf("Collection #%d:
    ",++cnt);
    24         
    25         if(sum%2)  //一定要加这个判断
    26         {
    27             printf("Can't be divided.
    
    ");
    28             continue;
    29         }
    30         sum/=2;
    31         memset( dp, 0, sizeof( dp ) );
    32         for( int  i = 1; i <= 6; i++ )   //枚举物品
    33         {
    34             int p = 1;
    35             while( p < rice[i].c )    //把物品二进制分开
    36             {
    37                 for( int j = sum; j >= rice[i].p * p; j-- )
    38                     if( dp[j] < dp[j - rice[i].p * p] + rice[i].p * p)
    39                         dp[j] = dp[j - rice[i].p * p] + rice[i].p * p;
    40 
    41                 rice[i].c -= p;
    42                 p <<= 1;  //相当于乘与2
    43             }
    44             for( int j = sum; j >= rice[i].p * rice[i].c; j-- ) //把二进制枚举后剩下的物品看成一个整体采用01背包
    45                 if( dp[j] < dp[j - rice[i].p * rice[i].c] + rice[i].p * rice[i].c )
    46                     dp[j] = dp[j - rice[i].p * rice[i].c] + rice[i].p * rice[i].c;
    47         }
    48         if(dp[sum]==sum)
    49         {
    50             printf("Can be divided.
    ");
    51         }
    52         else
    53         {
    54             printf("Can't be divided.
    ");
    55         }
    56         printf("
    ");
    57     }
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    13.Odoo产品分析 (二) – 商业板块(6) –采购(3)
    9.Odoo产品分析 (二) – 商业板块(4) –讨论(1)
    10.Odoo产品分析 (二) – 商业板块(5) –日历(1)
    8.Odoo产品分析 (二) – 商业板块(3) –CRM(2)
    7.Odoo产品分析 (二) – 商业板块(3) –CRM(1)
    the nearest point/vertex point of linestring
    Clojure的引用类型:var,ref,agent和atom
    clojure的delay future promise
    clojure的语法糖
    postgres select TOP X in group 查询每个组的前几名
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12617598.html
Copyright © 2011-2022 走看看