1. 程式人生 > >臺州 OJ 5072 Cow Exhibition 01背包

臺州 OJ 5072 Cow Exhibition 01背包

可能 put () string log 滾動 bsp pan max

給出 n 頭牛,每頭牛有兩個屬性 smartness 和 funness ,求從所有的牛裏選一些牛,使這些牛的 smartness + funness 的和最大,且 smartness 的和、funness的和都要大於零。

定義 dp[i][j] 表示前 i 頭牛在 smartness 為 j 時 funness 的最大值。

dp[i][j+s[i]] = max(dp[i-1][j+s[i]], dp[i-1][j] + f[i]) s[i]、f[i] 分別表示第 i 頭牛的 smartness 和 funness。

因為 smartness 可能為負,要保證在 dp 時下標要大於等於零,所以在 dp 的過程中將 j 加一個數,最後求答案時再轉化回原來的數。

代碼(用了兩個一維數組滾動優化):

#include <iostream>
#include <cstring>
using namespace std;

const int MAX = 2005;
const int INF = 0x3f3f3f3f;
const int zero = 100000; 

int n;
int now[MAX*100], pre[MAX*100];
int s[MAX], f[MAX];

int main(){
    freopen("input.txt", "r", stdin);
    int ans = 0, minS = 0, maxS = 0
; cin >> n; for(int i=1; i<=n; i++){ cin >> s[i] >> f[i]; if(s[i] >= 0 && f[i] >= 0){ //smartness 和 funness 都大於 0 的牛一定選 ans += s[i] + f[i]; i--; n--; }else if(s[i] < 0 && f[i] < 0){ //都小於 0 的一定不選
i--; n--; } } //初始化 memset(now, -INF, sizeof(now)); now[zero] = 0; memcpy(pre, now, sizeof(now)); //DP minS = maxS = zero; // 0 變成 100000,將 smartness 為負數的情況轉化為全部是正數 for(int i=1; i<=n; i++){ for(int j=minS; j<=maxS; j++){ now[j+s[i]] = max(pre[j+s[i]], pre[j] + f[i]); //smartness j+s[i] 時,funness 的最大值,考慮第 i 頭牛放不放 } minS = min(minS + s[i], minS); maxS = max(maxS + s[i], maxS); memcpy(pre, now, sizeof(now)); } int maxn = 0; for(int i=zero; i<=maxS; i++){ if(now[i] >= 0){ maxn = max(maxn, (i-zero) + now[i]); //要 - zero 轉化為原來的 smartness } } cout << ans + maxn; return 0; }

臺州 OJ 5072 Cow Exhibition 01背包