NYOJ1289 ABS(01 backpack, idea)

describe

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.

input

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.

output

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

sample input

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

sample output

 8 
 1 
 6

thinking

First of all, there is a container with infinite capacity. I will give you n potions. Each potion has a weight (which can be negative). To add potions to the container, after each addition, the weight in the container will become the absolute value of the difference between the weight p of the container and the weight q of the potion.

You can add the liquid medicine in any order and ask what the maximum weight of the liquid medicine in the final container is.

We think that negative numbers can always be added last, so we can save the negative ones and subtract them first (subtracting negative numbers equals adding positive numbers).

Put all the positive numbers in an array, sort from big to small. Here we have a greedy, the biggest one can definitely be put last. In this case, it must be the best. For the remaining numbers, we just need to find a way to make them the smallest. We can consider dividing them into two piles to make the difference between the two piles the smallest. In this way, the problem is transformed into the problem of nyoj stamp sharing half of you So, we only need to carry out 01 knapsack once, and then sum DP [v] is the difference between the two piles.

Code

#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;
}

Posted by ErnesTo on Sat, 21 Mar 2020 08:33:53 -0700