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;

}

posted @ 2012-04-30 15:53  yejinru  阅读(228)  评论(0编辑  收藏  举报