NOJ [1306] Divide The Apples

  • 问题描述
  • XP and EG both like eating apple. This day they bought a lot of apples. Then it was time for them to seperate these apples. They didn't want to get less apples than each other and cut the apples into pieces either. So they would get equal weight of apples. After they seperated the apples, the rest would be throw away. for example they bought 5 apples, their weight are 1 2 3 5 6 , XP will get apple of weight 1 2 and EG 3 , the rest of 5,6 will be throw away. The total weight they get is 3. But there is another better way. XP get the apples of weight 2 6 and EG 3 5 , the total weight the get is 8, and this is the best way. But they didn't know how to seperate the apples. So they ask you for help to get as many apples as possible.
  • 输入
  • The first contain a positive integer n indicate the number of apple(1<=n<=100). you can sure the total weight of the apple won't exceed 2000.
    The second line contain n integers indicate the weight of each apple.
  • 输出
  • A integer m,indicate the maximal weight XP and EG can get.

    刚看到这题的时候,我的第一想法是,求出和sum之后,先用sum/2来进行背包,看可不可以,如果不行就mid--,事实证明这不行
    ,
    本题可以这么想,一个苹果,要么是给第一个人,要么给第二个人,要么扔掉,那么类似01背包,用dp[i][j]表示第一个人拿了i重量的,第二个人拿了j重量的,如果dp[][]==1,说明此方案可行,否则为不行

    那么,状态转移方程很容易就出来了,dp[i][j]=(dp[i-apple[k]][j])||(dp[i][j-apple[k]]),
    所以循环的话,也和01背包一样。逆序,捡到0,因为每一个苹果只有一个

    #include<stdio.h>
    #include<string.h>

    int dp[1100][1100];
    int apple[1005];
    int main()
    {
    int n;
    while(~scanf("%d",&n))
    {
    memset(dp,0,sizeof(dp));
    int i,j,k,sum=0;
    for(i=1;i<=n;i++)
    {
    scanf("%d",&apple[i]);
    sum+=apple[i];
    }
    dp[0][0]=1;
    //对于苹果,要么给1,要么给2,要么扔掉,先枚举每人拿到的重量
    for(k=1;k<=n;k++)
    for(i=sum/2;i>=0;i--)
    for(j=sum/2;j>=0;j--)
    {
    if((i>=apple[k] && dp[i-apple[k]][j]) || (j>=apple[k] && dp[i][j-apple[k]]))
    dp[i][j]=1;
    }
    for(i=sum;i>=0;i--)
    if(dp[i][i])
    break;
    printf("%d\n",i);

    }
    return 0;
    }


你可能感兴趣的:(NOJ [1306] Divide The Apples)