題意:每頭牛有smart值和funness值,求出在smart值的和>0&&funness值>0的情況下,smart值和funness值的總和最大。
分析:轉化成01揹包問題,每頭牛選不選就相當於每件物品選與不選,把牛的smart值看做體積,funness看做價值,則對應dp[j]表示前i件物品放入到體積爲j的揹包裏所達到的最大價值
然後對於一個0-1揹包問題,我們的遞推公式是
for(int i=W;i>=w[i];i--)
dp[i]=dp[i-w[i]]+v[i]
在這裏有一個比較棘手的點就在於如果我們將smart值作爲體積,那麼體積會有負數,因此我們將數組開到,大於MAX的用於表示正數,小於MAX用於表示負數,比如就表示smart爲1時,最大的funness的值,就代表smart和爲時,最大的funness的值。然後對每一個的元素,我們從右向左進行遍歷
for (int j = sum; j >= smart[i]; j--)//正:從右向左
if (dp[j - smart[i]] != -inf) {
dp[j] = max(dp[j], dp[j - smart[i]] + fun[i]);
}
需要注意的是,這裏的sum是我們爲了簡化程序所計算的所有正的smart的和,也是最大的smart,因此的索引值不會超過他,而索引值又必須大於0,因此,相反對於每一個的元素,我們有
for (int j = 0; j <= sum; j++)//負:從左到右
if (dp[j - smart[i]] != -inf) {
dp[j] = max(dp[j], dp[j - smart[i]] + fun[i]);
}
最後計算結束後,我們統計所有KaTeX parse error: Expected 'EOF', got '&' at position 11: i\geq MAX &̲& dp[i]>0的滿足條件的的最大值即可。
#define inf 0x3f3f3f3f
#define vec vector<int>
#define P pair<int,int>
#define ll long long
#define MAX 100005
int N, dp[MAX*2], F[105], T[105];
int main() {
while (scanf("%d", &N) != EOF) {
fill(dp, dp + 2*MAX, -inf);
dp[MAX] = 0;
int sum = MAX;
for (int i = 1; i <= N; i++) {
scanf("%d %d", &F[i], &T[i]);
if (F[i] > 0)sum += F[i];
}
for (int i = 1; i <= N; i++) {
if (F[i] >= 0) {
for (int j = sum; j >= F[i]; j--)//正:從右向左
if (dp[j - F[i]] != -inf) {
dp[j] = max(dp[j], dp[j - F[i]] + T[i]);
}
}
else
for (int j = 0; j <= sum; j++)//負:從左到右
if (dp[j - F[i]] != -inf) {
dp[j] = max(dp[j], dp[j - F[i]] + T[i]);
}
}
int ma = 0;
for (int i = MAX; i <= sum; i++)
if (dp[i] > 0 && dp[i] + i - MAX > ma)
ma = dp[i] + i - MAX;
cout << ma << endl;
}
}