Codeforces 148E(Porcelain)

題意:嬌生慣養的公主總愛發脾氣,她每一次發脾氣都會摔壞一個價值val的瓷器,這些瓷器放在n個架子上,每個架子有ai個花瓶,她每次只摔架子最左或最右的瓶子,求這摔壞m個瓷器總和的最大價值

題目抽象:有N行數,每行有ai個數,每次只能從每行數的頭尾取數,取後將其刪除,然後就會產生新的頭尾;

求從這N行數中取M個數能取得的最大值;

思路:觀察下題目,先從一行入手,可以發現每一行取出來的數一定是連續的,有兩種情況:1、取出來的數一段在前面取,一段在後面取;2、取出來的數全部在前面取或者全部在後面取;發現這個規律之後,可以先預處理每行取k個數能取到的最大值( 1<= k <= ai),即第i行取k個數的最大值,保存在dp[i][k]中;然後對它進行揹包,這個和01揹包有點不同,就是同一行中只能選擇一種取數方案;

#include <cstdio>
#include <climits>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 110;
const int V = 10010;
int sum[N], val, dp[N], bac[V];

int main(){
	int n, M, i, j, k, l, res = INT_MIN;
	scanf("%d%d", &n, &M);
	for(i = 1;i <= n;i++){
		scanf("%d", &k);
		for(j = 1;j <= k;j++){
			scanf("%d", &sum[j]);
			sum[j] += sum[j - 1];
		}
		int tmp = INT_MIN;
		for(l = 1;l <= k;l++){
			int fir = 1, last = k - l;
			for(j = 1;last <= k;j++){
				tmp = max(tmp, sum[k] - (sum[last] - sum[fir - 1]));
				fir++, last++;
			}
			dp[l] = tmp;
		}
		for(int vv = M;vv >= 1;vv--)
			for(j = 1;j <= k&&vv - j >= 0;j++){
				bac[vv] = max(bac[vv], bac[vv - j] + dp[j]);
				res = max(res, bac[vv]);
		}
	}
	cout << res << endl;
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章