1. 程式人生 > >[USACO]奶牛會展(背包)

[USACO]奶牛會展(背包)

while 最好的 include 價值 證明 namespace turn read 輸入

[USACO]奶牛會展

題目背景

奶牛想證明它們是聰明而風趣的。為此,貝西籌備了一個奶牛博覽會,她已經對N 頭奶牛進行

了面試,確定了每頭奶牛的智商和情商。

題目描述

貝西有權選擇讓哪些奶牛參加展覽。由於負的智商或情商會造成負面效果,所以貝西不希望出展奶牛的智商之和小於零,或情商之和小於零。滿足這兩個條件下,她希望出展奶牛的智商與情商之和越大越好,請幫助貝西求出這個最大值。

輸入輸出格式

輸入格式:

? 第一行:單個整數N,1 ≤ N ≤ 400

? 第二行到第N + 1 行:第i + 1 行有兩個整數:Si 和Fi,表示第i 頭奶牛的智商和情商,?1000 ≤ Si; Fi ≤ 1000

輸出格式:

輸出格式

? 單個整數:表示情商與智商和的最大值。貝西可以不讓任何奶牛參加展覽,如果這樣做是最好的,輸出0

輸入輸出樣例

輸入樣例#1:

5
-5 7
8 -6
6 -3
2 1
-8 -5

輸出樣例#1:

8

說明

選擇第一頭,第三頭,第四頭奶牛,智商和為?5+6+2 = 3,情商和為7?3+1 = 5。再加

入第二號奶牛可使總和提升到10,不過由於情商和變成負的了,所以是不允許的

被綠題支配的恐懼??? 最開始看到題目是懵逼的,之後看了題解才明白。將智商和情商分別看作容量和價值來做01背包。
\(F[i]\)表示當智商總和為\(i\)時,情商的最大值。
\[F[i]=max(F[i-a[k]]+b[k])\]


但是有一點我們需要註意,在狀態轉移的過程中,智商和情商是允許為負數的,所以我們為了考慮到這種情況,將智商往右移\(sa\)個單位。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int read()
{
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
    while
(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*w; } int dp[800010],a[410],b[410]; int main() { int sa=0,ans=0; int n=read(); for(int i=1;i<=n;i++) { a[i]=read();b[i]=read(); if(a[i]>0) sa+=a[i]; } sa=sa*2; memset(dp,-0x3f,sizeof(dp)); dp[sa/2]=0; for(int i=1;i<=n;i++) { if(a[i]>=0) for(int j=sa;j>=a[i];j--) { dp[j]=max(dp[j],dp[j-a[i]]+b[i]); } else for(int j=0;j<=sa-a[i];j++) { dp[j]=max(dp[j],dp[j-a[i]]+b[i]); } } sa/=2; for(int i=0;i<=sa;i++) { if(dp[i+sa]>=0)//這句判斷一定不能忘記了 ans=max(ans,i+dp[i+sa]); } cout<<ans; }

[USACO]奶牛會展(背包)