lightoj 1126 - Building Twin Towers DP

给定n个数字,然后选择一些数字分成两堆,这两堆的和相等,求最大的和...

首先求一下所有数字的和...那么最后结果肯定小于等于sum/2。

然后范围50W...那么肯定滚动数组先,然后两数字的差当做第二维...

两数字的差要修正一下范围100W,遍历也要100W..然而可以并不需要,因为我们可以dp[i][j]代表选择前i个数字后两数字相差为j的最大值,那么最大值减去差值就是最小值。如果最小值加了某个数字大于最大值,可以换过来...

对于一个数字来言,可以放在第一个数字(不能爆sum),放在第二个数字(超过第一个数字or没超过)或者不选...

#include
using namespace std;
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
int dp[2][500200];
int a[60];
int main()
{
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++)
    {
        int n,sum=0;
        scanf("%d",&n);
        for(int i=0;i=a[i])
                    dp[s^1][j-a[i]]=max(dp[s^1][j-a[i]],dp[s][j]);//给小的数字加,没超过大的
                else
                    dp[s^1][a[i]-j]=max(dp[s^1][a[i]-j],dp[s][j]+a[i]-j);//给小的数字加完超过大的了
            }
        }
        printf("Case %d: ",cas);
        if(dp[s^1][0]==0) printf("impossible\n");
        else printf("%d\n",dp[s^1][0]);
    }
    return 0;
}


你可能感兴趣的:(动态规划)