NYOJ1289 ABS(01背包,思路)

描述

Mr.Ha is a famous scientist .He has just not got a kind of magic
medicine called Entropy Cracker.The medicine was preserved in V
bottles,and the i-th (1≤i≤N) bottle contains V liters of medicine.To
make the magic available, he needs to put the medicine from all the
bottles together.

Due to mixing medicine is a dangerous action, Mr.Ha takes a huge
container with infinite volume and decides only to pour a whole bottle
of medicine into the container each time.After adding a p liter`s
bottle of medicine into the container with q liters of medicinein
it,the resulted volume of medicine in the container will be |p-q|
liters.

Initially the container is empty ,and Mr.Ha can put the bottles of
medicine into the container by arbitrary order.Finally if there are R
liters of medicine in the container ,Mr.Ha will be able to use the
magic to increase the time for R seconds every day so that he can
achieve more work! Help Mr.Ha to make an arrangement so that the
resulted R is maximum.

输入

The first line contains an integer T,indicating the number of test
cases. For each test case ,the first line contains an integer N
1≤N≤200,indicating the number of botters, and the second line contains
V (|vi|<=500),indicating the volume of medicine in each bottle
Attention the volume may be negative as a result of magic The sum of
N in all test cases will not exceed 2000.

输出

For each test case , output the case number in the format of the
format of the sample ,and an Integer ,the maximum seconds Mr.Ha will
able to increase

样例输入

3 
4 
1  2  2  9
1 
-1 
10 
1  3  0  0  0  1  2  7  3  7  

样例输出

 8 
 1 
 6

思路

先说题意,有一个容量无限大的容器,给你n个药水,每个药水有一个权值(可以为负),要往容器里面添加药水,每次添加后,容器里面的权值就会变成容器的权值p和药水的权值q的差的绝对值。

你可以以任意顺序添加药水,问最后容器里面药水的权值最大是多少。

我们考虑负数一定可以最后加,所以直接把负的存下来,先减去(减去负数等于加上正数)。

把所有的正数放在一个数组里面,从大到小排序,在这里我们进行一次贪心,最大的肯定可以最后放,这样的情况一定是最优的,剩下数的我们只要想办法使他们最小就行了,我们可以考虑分成两堆,使这两堆的差最小,这样问题就转化成了nyoj邮票分你一半这个题目,只需要进行一次01背包,随后sum-dp[v]就是两堆的差。

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include<list>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f3f
typedef long long ll;
const int N=50000+20;
int a[N],dp[N];
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    int t,n,x;
    scanf("%d",&t);
    while(t--)
    {
        mem(a,0);
        mem(dp,0);
        scanf("%d",&n);
        int ans=0,len=0,sum=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&x);
            if(x<0)ans-=x;
            else
            {
                a[len++]=x;
                sum+=x;
            }
        }
        sort(a,a+len,cmp);
        ans+=a[0];
        sum-=a[0];
        int v=sum/2;
        for(int i=1; i<len; i++)
            for(int j=v; j>=a[i]; j--)
                dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
        sum=sum-2*dp[v];
        printf("%d\n",ans-sum);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/80195905