链接:
@[toc]

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

终于Alice走出了大魔王的陷阱,可是现在傻傻的她忘了带武器了,这可如何是好???这个时候,一个神秘老人走到她面前答应无偿给她武器,但老人有个条件,需要将所选武器分别放在天平的两端,若天平平衡则可以将天平上的所有武器拿走,还好这个天平锈迹斑斑,只要两端重量相差小于等于m就会保持平衡,Alice傻傻的认为越重的武器越好,求Alice最多能拿走的武器总重量。(不限操作次数)

输入描述:

第一行2个整数 n, m; 第二行n个整数x,分别表示n件武器的重量。 1 <= n <= 100; 0 <= m <= 100; 1 <=
x <= 100;

输出描述:

一个整数,表示Alice最多能拿走的武器总重量。

示例1
输入

5 4
1 5 61 65 100

输出

132

说明
可以称两次,第1次:(1 ; 5),第二次(61 ; 65)。
示例2
输入

5 0
10 20 30 40 100

输出

200

说明
称一次,(10,20,30,40 ; 100)。

题解:

第一感觉是dp
对于每个物品我们都要做出选择:放在天平的左边,放在天平的右边,不选择。
那么我们就可以去找递推式:
dp[i][j]表示前i样物品进行选择后,此时天平两端的重量差为j的时候,最大质量是多少,我们定义这个质量差为 左减右,那么左边放物品质量差增大,右边放质量差变小
我们想想dp[i][j]是怎么来的?
(a[i]表示第i件物品的质量)
如果我们选择第i件物品,放在天平的左边,那么dp[i][j]就是从dp[ i -1 ] [ j - a [ i ] ]来的(将第i件物品选择前,质量差为j-a[i])转移过来
同理:如果放在天平的右边,那么dp[i][j]就是dp[i-1][j+a[i]]转移而来的
如果不放,那就是dp[i-1][j]直接转移过来
我们要找到最大的情况,就是上面三个取最大值
dp[i][j] = max(dp [ i -1 ] [ j ] , d p [ i - 1 ][ j - a [ i ] ] + a [ i ] ,d p [ i - 1 ] [j +a [ i] ] + a [ i ] )
因为题目有限定这个质量差的上限,所以最后我们求出这个范围内的最大质量即可
max(sum,dp[n][i])
大致就是这样

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+4;
int dp[100][maxn];
int a[maxn];
int max(int a,int b,int c)
{
    if(a>=b&&a>=c)return a;
    else if(b>=a&&b>=c)return b;
    else if(c>=b&&c>=a)return c; 
}
int main()
{
    memset(dp,-0x3f,sizeof(dp));
//    cout<<dp[0][0]<<endl;
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    int sum=0;
    dp[0][0]=0;
    for(int i=1;i<=n;i++)
    for(int j=0;j<=maxn;j++)
    {
         dp[i][j] = max(dp[i-1][j],dp[i-1][abs(j-a[i])]+a[i],dp[i-1][j+a[i]]+a[i]);
    } 
    for(int i=0;i<=m;i++)
    {
        sum=max(sum,dp[n][i]);
    }
    printf("%d",sum);
    return 0;
}