dp02

元始天尊123發表於2024-10-15

dp02

今天刷了一道dp問題

題目描述

小明過生日的時候,爸爸送給他一副烏龜棋當作禮物。

烏龜棋的棋盤是一行 N 個格子,每個格子上一個分數(非負整數)。棋盤第 1格是唯一的起點,第 N格是終點,遊戲要求玩家控制一個烏龜棋子從起點出發走到終點。
烏龜棋中 M張爬行卡片,分成 4 種不同的型別(M 張卡片中不一定包含所有 4 種型別的卡片,見樣例),每種型別的卡片上分別標有
1,2,3,4 四個數字之一,表示使用這種卡片後,烏龜棋子將向前爬行相應的格子數。遊戲中,玩家每次需要從所有的爬行卡片中選擇一張之前沒有使用過的爬行卡片,控制烏龜棋子前進相應的格子數,每張卡片只能使用一次。

遊戲中,烏龜棋子自動獲得起點格子的分數,並且在後續的爬行中每到達一個格子,就得到該格子相應的分數。玩家最終遊戲得分就是烏龜棋子從起點到終點過程中到過的所有格子的分數總和。

很明顯,用不同的爬行卡片使用順序會使得最終遊戲的得分不同,小明想要找到一種卡片使用順序使得最終遊戲得分最多。

現在,告訴你棋盤上每個格子的分數和所有的爬行卡片,你能告訴小明,他最多能得到多少分嗎?

程式碼

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<map>
#include<unordered_map>
#include<stack>
#include<vector>
typedef long long LL;
using namespace std;
#define INF 0x3f3f3f3f
typedef pair<int,int>PII;
#define x first
#define y second
const int N=360,M=130;
int dp[2][42][42][42][42];
int A[N],B[N],st[N];
int num[5];
int n,m,k;

int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>A[i];
	}
	for(int i=0;i<m;i++){
		cin>>k;
		num[k]++;
	}
	for(int i=1;i<=m;i++){
		for(int j=0;j<=min(num[1],i);j++){
			for(int k=0;k<=min(num[2],i-j);k++){
				for(int u=0;u<=min(num[3],i-j-k);u++){
					int v=i-j-k-u;
					if(v>num[4])continue;
					dp[i%2][j][k][u][v]=dp[(i-1)%2][j][k][u][v];
					if(j!=0)
					dp[i%2][j][k][u][v]=max(dp[i%2][j][k][u][v],dp[(i-1)%2][j-1][k][u][v]+A[j+k*2+u*3+4*v+1]);	
					if(k!=0)
						dp[i%2][j][k][u][v]=max(dp[i%2][j][k][u][v],dp[(i-1)%2][j][k-1][u][v]+A[j+k*2+u*3+4*v+1]);
					if(u!=0)
						dp[i%2][j][k][u][v]=max(dp[i%2][j][k][u][v],dp[(i-1)%2][j][k][u-1][v]+A[j+k*2+u*3+4*v+1]);	
					if(v!=0)
						dp[i%2][j][k][u][v]=max(dp[i%2][j][k][u][v],dp[(i-1)%2][j][k][u][v-1]+A[j+k*2+u*3+4*v+1]);	
				}
			}
		}
	}
	cout<<dp[m%2][num[1]][num[2]][num[3]][num[4]]+A[1];
	return 0;
}