ural 1005 Stone Pile DP

/*

 

题目:

    把石头分成两堆,问最小的重量差值为多少。

 

分析:

    先求和,然后用和的一半转为01背包。转移方程为:

    dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+w[i]);

    缩小维度后为dp[j] = max(dp[j],dp[j-w[i]]+w[i]);

 

*/

#include <iostream>

#include <cstring>

#include <cstdio>

using namespace std;

const int X = 2000010;

int dp[X],w[25],n;

int main()

{

    freopen("sum.in","r",stdin);

    freopen("sum.out","w",stdout);

    while(cin>>n)

    {

        if(n==1)    //输入为1时,直接输出即可

        {

            scanf("%d",&w[0]);

            cout<<w[0]<<endl;

            continue;

        }

        int sum = 0,temp,ans;

        for(int i=1;i<=n;i++)

        {

            scanf("%d",&w[i]);

            sum += w[i];

            dp[i] = 0;

        }

        temp = sum>>1;  //除二

        dp[0] = 0;

        for(int i=1;i<=n;i++)   //状态转移方程

            for(int j=temp;j>=w[i];j--)

                dp[j] = max(dp[j-w[i]]+w[i],dp[j]);

        for(int i=temp;i>=0;i--)

            if(dp[i]!=0)    //当不为零时即为所求的一半石子重量

            {

                ans = dp[i];

                break;

            }

        ans = 2*ans-sum;

        ans = max(ans,-ans);

        cout<<ans<<endl;

    }

 

    return 0;

}

转载于:https://www.cnblogs.com/yejinru/archive/2012/04/30/2476962.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值