中國計量大學現代科技學院第四屆“中競杯”程式設計校賽(同步賽) F.爬塔(DP)

Chstelove發表於2020-12-07

題目連結:https://ac.nowcoder.com/acm/contest/9680/F

題目描述:
高川最喜歡的遊戲當屬 Slay the Spire,這是一款爬塔遊戲,你需要從一座塔的底部一直爬到頂部,在爬塔的過程中,塔的每一層都有許多的寶物等你來拿。

高川從塔的左側開始攀爬,從底部爬到頂部,再從右側從頂部逐步下到底部。塔總共有 n 層,每一層都有很多寶物從左到右排列。在左側攀爬時,他只能從每層的最左邊按順序取寶物,在右側下降時,他只能從每層的最右邊按順序取寶物。每個寶物都有一個價值,他最多拿 m 個寶物,他想知道自己從塔上下來時,最多可以拿的寶物價值和是多少。

輸入描述:
第一行輸入兩個正整數 n 和m 。表示塔的層數和最多能選的個數。

接下來 n 行,每行先輸入一個數字 x。表示這一層寶物的個數。接下來輸入 x 個正整數,表示每個寶物的權重 c。1≤n,x,c≤100,1≤m≤10000。
輸入保證可挑選的物品大於等於 m 個。

輸出描述:
輸出一個整數表示高川能拿走的最大價值和。

示例1:
輸入:
2 3
2 3 2
4 1 4 1 5

輸出:
10

解題思路:
        因為每一層只能從左往右或者從右往左的順序取寶物,所以可以先計算出每一層寶物價值的字首和與字尾和分別表示從左往右與從右往左取寶物的價值和,接著維護一個ans陣列,ans[i][j]表示第i層取j件寶物所能達到的價值最大值。最後進行DP,dp[i]表示拿取i件寶物所能獲得的最大價值,最終答案為dp[m]。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e2+10;
const int maxm = 1e4+10;

int a[maxn][maxn];
int x[maxn],ans[maxn][maxn];
int pref[maxn][maxn],suf[maxn][maxn];
int dp[maxm];

int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&x[i]);
		for(int j=1;j<=x[i];j++){
			scanf("%d",&a[i][j]);
			pref[i][j]=pref[i][j-1]+a[i][j];
		}
	}
	for(int i=1;i<=n;i++)
		for(int j=x[i];j>=1;j--)
			suf[i][j]=suf[i][j+1]+a[i][j];

	for(int i=1;i<=n;i++)
		for(int j=0;j<=x[i];j++)
			for(int k=0;j+k<=x[i];k++)
				ans[i][j+k]=max(ans[i][j+k],pref[i][j]+suf[i][x[i]-k+1]);

	for(int i=1;i<=n;i++)
		for(int j=m;j>0;j--)
			for(int k=x[i];k>0;k--)
				if(k<=j)
					dp[j]=max(dp[j],dp[j-k]+ans[i][k]);

	printf("%d\n",dp[m]);
	return 0;
}

相關文章