poj2184 Cow Exhibition [01 backpack] + [negative number processing] + (to find the maximum sum of two variables)

Question link: https://vjudge.net/contest/103424#problem/G

 

Topic meaning:

Given N cows, each with intelligence and a sense of humor, and the weirdest thing about this topic is that they can be negative numbers! ! Now I ask you to find the maximum value of the total number of intelligence points and the total number of sense of humor among the cows. Of course, the total number of intelligence points must be greater than or equal to zero, and so is the total number of sense of humor.

 

Problem solving ideas:

Reprinted from >>> Daniel Blog

For each cow, we have two options, either choose or choose. Seeing this, it feels like the 01 backpack, but with 2 variables that characterize this state, intelligence, humor, and they may be negative. 
If you choose dp to solve this problem, we need to find a way to convert it into 01 knapsack.

Here's how to convert the 01 backpack. 
First, the template below is a 1D array solution to the knapsack problem.

dp[i] = max(dp[i],dp[i-w[i]]+v[i])

First, for two variables, intelligence and sense of humor, we define i as the sum of intelligence of the first i cows, and dp[i] stores the maximum value of sense of humor when the sum of intelligence is i at this time. Some people may ask, the question asks us to find the maximum value of the total number of intelligence and sense of humor. What this dp finally obtains is only the maximum value of the total number of sense of humor? It doesn't matter, after finding the whole dp, add each d[i] and i to see who is bigger, don't forget, i is the sum of intelligence. 

This step is to lock the variable.

 

Before starting the next step, let's define the size of the dp array. 
There are at most 100 cows, and the intelligence range of each cow is between -1000 – 1000, 
then their sum is in the range of -1000*100 – 100*1000, that is, our dp should be 100*1000 *2 It's so big. Then imitate the coordinate system and find an origin in the numbers of 100*1000*2. Naturally, this is symmetrical. Obviously, the far point is 100*1000, which is 100000. Greater than 100000, the total intelligence is greater than 0, less than 100000, the total intelligence is less than 0.

 

Of course, it is impossible for us to access such a large array, so we need to mark it. Since the maximum value is here, we initialize the array to a very small integer, inf = -100000000.

Well, the next step is to deal with the key negative numbers. The processing of negative numbers is obviously different from positive numbers, but they are all dp, but the way of processing has changed.

 

s[i] Intelligence of the i-th cow
f[i] the sense of humor of the ith cow
for i : 1 to N     // represents the first cow 
    if (intelligence is negative){
         // processing 
    }
     else  if (intelligence is positive or 0){
         // processing 
    }

First, positive numbers, each cow has a choice or not, imitating the 01 backpack

for(int v = 100*1000*2;v>=s[i];v--)
    if(dp[v-s[i]]>inf)
        dp[v] = max(dp[v],dp[v-s[i]]+f[i])

 

If you know the optimization of the 01 knapsack, the above is very simple. Reverse the cycle to ensure that each state can access the previous state.

v = 5 ;
dp [5] = max(dp[5],dp[5-s[i]]+f[i])

 

s[i] > 0,5-s[i] is obviously less than 5. At this time, dp[5-s[i]] still saves the value of the previous state, so we can use it with confidence.

Then comes the judgment condition, dp[vs[i]]>inf, remember that we initialized the array representing the sum of intelligence values ​​to inf at the beginning? If, dp[vs[i]]<=inf, it means that there is no such intelligence value and it is not used, that is, dp[v] is a state without dp[vs[i]], since we don't have it, we ignore it.

 look at negative numbers

 

for(int v = s[i];v<100*1000*2;v++)
    if(dp[v-s[i]]>inf)
        dp[v] = max(dp[v],dp[v-s[i]]+f[i])

 

If you look closely, you will find that the loop conditions are different. Why is this possible? 
In fact, you can refer to the space optimization of the 01 backpack and the space optimization of the complete backpack.

 

Whether it is a positive number or a negative number, we all push dp[v] to ensure that it is derived from the previous state. For positive numbers, the total intelligence of the previous state is smaller than the current state. On the contrary, for negative numbers, the total intelligence of the previous state is greater than the current state, s[i] < 0, vs[i] > v, if we are still looping in reverse order, when pushing dp[v], it is more The big d[vs[i]] has already changed, not the previous state, then there is a problem with our recursion. For this problem, we can just loop forward.

Finally, after dp

come a cycle

ans = 0 ;
 for i: 100 * 1000 to 100 * 1000 * 2      The sum of intelligence should be positive
     if (dp[i]>= 0 )
        ans = max(ans,i - 100*1000 + dp[i]);

i-100*1000 is equal to the sum of the intelligence values ​​at this time, because we offset the array.

 

The AC codes are as follows:

#include <stdio.h>  
#include <string.h>  
#include <algorithm>  
using namespace std;

int dp[200005];
const int inf = 1 << 30;

intmain ()
{
    int n, s[105], f[105], i, j, ans;
    while (~scanf("%d", &n))
    {
        for (i = 0; i <= 200000; i++)
            dp[i] = -inf;
        dp[100000] = 0;
        for (i = 1; i <= n; i++)
            scanf("%d%d", &s[i], &f[i]);
        for (i = 1; i <= n; i++)
        {
            if (s[i]<0 && f[i]<0)
                continue;
            if (s[i]>0)
            {
                for (j = 200000 ; j >= s[i]; j--) // If s[i] is a positive number, then we will backpack from big to small   
                    if (dp[j - s[i] ]]>- inf)
                        dp[j] = max(dp[j], dp[j - s[i]] + f[i]);               
            }
            else
            {
                for (j = s[i]; j <= 200000 + s[i]; j++) // For negative numbers, it needs to be reversed   
                    if (dp[j - s[i]]>- inf)
                        dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
            }
        }
        ans = - inf;
         for (i = 100000 ; i <= 200000 ; i++) // Because the interval 100000~200000 is the integer represented, then the i at this time is the s[i] in the previous backpack, if dp at this time [i]
                                           is // if f[i] is greater than or equal to 0, we add s[i] (i at this time), and then subtract 100000 as the limit to get the answer   
        {
             if (dp[i ] >= 0 )
                ans = max(ans, dp[i] + i - 100000);
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

2018-04-30

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325057283&siteId=291194637