POJ 2184 Cow Exhibition

来源:互联网 发布:aspnet源码 编辑:程序博客网 时间:2024/06/03 18:51

题目链接

题意:给出num(num<=100)头奶牛的S和F值(-1000<=S,F<=1000),要求在这几头奶牛中选出若干头,使得在其总S值TS和总F值TF均不为负的前提下,求最大的TS+TF值

题解:直观感受就是平衡,想要s就可能会f带来很大的负值,这样就是用背包dp的最标准的情况,把一维当做dp数组的维数(比如s),然后将f当做第二维,在同样的s下要最大的f。但是不同的是有两点:数组中加一个key平衡值,用来表示s的负数情况,第二:01背包更新体积的时候,如果当前的s是正的话,倒着扫,如果是负的话,正着扫,满足01背包。

重点:需要平衡两个值,不可兼得,需要枚举,枚举想dp背包。

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <ctype.h>#include <limits.h>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <map>#include <stack>#include <set>#include <bitset>#define CLR(a) memset(a, 0, sizeof(a))#define REP(i, a, b) for(int i = a;i < b;i++)#define REP_D(i, a, b) for(int i = a;i <= b;i++)typedef long long ll;using namespace std;const int maxn = 200000 + 10;const int INF = INT_MAX;const int key = 200000;const int mid = 100000;//中间的平衡值int dp_last[maxn], dp[maxn];//以前写的代码,还是用的两个数组来一个表示没更新的,一个表示更新过的,每次拷贝一下,比较传统的写法,也可以01交换。int n, s[110], f[110];//上面的dp写法可以很好地减小错误的发生,但是没有直接更新一个数组更标准。void get_dp(){    int x = n*1000;    REP_D(i, 0, key)    {        dp_last[i] = INF;        dp[i] = INF;    }    dp_last[mid + s[1]] = f[1];    dp_last[mid + 0] = 0;    dp[mid + s[1]] = f[1];    dp[mid + 0] = 0;    REP_D(i, 2, n)//01背包,用上一次的dp来更新这一次的dp,注意平衡值。但是就不用管倒序或者正序扫了。    {        REP_D(j, 0, key)        {            dp[j] = dp_last[j];            if(j - mid - s[i]  + mid >= 0 && j - mid - s[i]  + mid <= key)            {                if(dp_last[j - mid - s[i]  + mid] != INF)                {                    if(dp[j] + j < dp_last[j - mid - s[i]  + mid] + f[i] + j)                        dp[j] = dp_last[j - mid - s[i]  + mid] +f[i];                }            }        }        REP_D(j, 0, key)        {            dp_last[j] = dp[j];        }    }}void solve(){    get_dp();    int ans = 0, x;    //x = n*1000;    REP_D(i, mid, key)    {        //int xx = i - x;        if(dp[i] >= 0 && dp[i] != INF)        {            //printf("%d %d is  %d\n")            ans = max(ans, dp[i] + i - mid);        }    }    printf("%d\n", ans);}int main(){    //freopen("2Bin.txt", "r", stdin);    //freopen("3Bout.txt", "w", stdout);    while(scanf("%d", &n) != EOF)    {        REP_D(i, 1, n)        {            scanf("%d%d", &s[i], &f[i]);            //s[i] += 1000;            //f[i] += 1000;        }        solve();    }    return 0;}


0 0