描述
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;
}