标签:pac algorithm lan ber add 范围 竞赛 include sep
5 -5 7 8 -6 6 -3 2 1 -8 -5
8
本题难点一:智商与情商是每头奶牛的两种属性,就和东西的重量和价值一样,属于0-1背包问题。
本题难点二:智商情商可以是负数,但是数组下标不允许是负数,所以得加上bias,而这个bias就是总智商的最小值的绝对值即100头牛智商全为最小-1000,也就是bias = 100000,所以范围是0-200000(因为最大是100000,再加上bias就是)。但是情商可以不用加bias,因为dp的值可以是负数。
本题难点三:在一维dp数组情况下原来情商大于等于0是j从大到小遍历的,因为这样可以保证dp[i - 1][j - s[i]]的对应一位dp数组dp[j - s[i]]在dp[j]之后再修改,否则之前修改的话dp[j - s[i]]的值就对应dp[i][j - s[i]]而不是dp[i - 1][j - s[i]]的值,但是如果f[i]小于0,那么dp[i - 1][j - s[i]]就要在dp[i - 1][j]的右边也就是j - s[i] > j,因此如果还是j从大到小就会造成dp[i - 1][j - s[i]]的对应的值dp[j - s[i]]实际上对应dp[i][j - s[i]]的值,因为j - s[i] > j,所以j从大到小的话在dp[j]之前就已经修改好了dp[j - s[i]]的值,就会造成错误,所以此时应当从小到大遍历。综上所述当s[i] >= 0,从大到小,s[i] < 0,从小到大遍历j。
AC代码:
#include <stdio.h> #include <algorithm> using namespace std; const int INF = 0x3fffffff; int s[105], f[105];//s智商,f情商 int dp[200005];//从前i头奶牛中选取奶牛使得的智商为i - bias时,情商的最大值 int ans; int main(void) { int n; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%d %d", &s[i], &f[i]); } fill(dp, dp + 200005, -INF);//初始化为不可达 dp[100000] = 0;//实际上对应前0种,也就是初始状态下,智商,情商均为0,因为智商为0时加上bias就是100000 for(int i = 0; i < n; i++) { if(s[i] < 0) { for(int j = 0; j - s[i] <= 200000; j++) if(dp[j - s[i]] != -INF) dp[j] = max(dp[j], dp[j - s[i]] + f[i]); } else { for(int j = 200000; j >= s[i]; j--) if(dp[j - s[i]] != -INF) dp[j] = max(dp[j], dp[j - s[i]] + f[i]); } } for(int i = 100000; i <= 200000; i++)//从智商为0开始遍历,也就是数组下标为bias开始 { if(dp[i] >= 0)//如果智商可达到i且情商大于等于0 ans = max(ans, dp[i] + i - 100000); } printf("%d\n", ans); return 0; }
挑战程序设计竞赛2.3习题:Cow Exhibition POJ - 2184
标签:pac algorithm lan ber add 范围 竞赛 include sep
原文地址:https://www.cnblogs.com/jacobfun/p/12240430.html