P10111 [GESP202312 七级] 纸牌游戏

题目

传送门

思路

一眼动态规划%%%

状态定义

定义dp[i][j][k]为执行到第i张牌时换了j次牌并且牌的大小为k

转移方程

第一种

我们的第一种转移方程肯定是没有换牌的时候,我们肯定要从上一个状态中原封不动的取走,此时转移方程为dp[i][j][k]=dp[i-1][j][k]+f,这里的f是可以获得的分数

第二种

我们的第二种转移方程肯定是换牌的时候,我们从余下的俩种情况取,此时转移方程为dp[i][j][k]=max(dp[i][j][k],max(dp[i-1][j-1][(k+1)%3],dp[i-1][j-1][(k+2)%3])+f-b[j])

初始化

我们第1轮一定是没有换牌的,所以我们的初始化为

for(int k=0;k<=2;k++){//0/1/2
		dp[1][0][k]=pd(c[1],k)*a[1];
	}

pd函数是为了方便于判断胜负关系的

答案

我们最终的答案在第n张牌的第j次换牌并且牌为k的位置,所以我们只要遍历j,k即可

int ma=-0x3f3f3f;
	for(int j=0;j<n;j++){
		for(int k=0;k<=2;k++){
			ma=max(ma,dp[n][j][k]);
		}
	}
	cout<<ma;

代码

有注释版

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n;
int a[N],b[N],c[N];
int dp[N][N][3];
//小杨:x  我: y
//y获胜,2   平局返回1   y失败返回0
int pd(int x,int y){
	if(x==y) return 1;
	else if(y-1==x || y+2==x) return 2;
	else return 0;
}
int main( )
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<n;i++) cin>>b[i];
	for(int i=1;i<=n;i++) cin>>c[i];
	memset(dp,-0x3f3f3f,sizeof(dp));
	//第1轮一定是没有换牌
	for(int k=0;k<=2;k++){//0/1/2
		dp[1][0][k]=pd(c[1],k)*a[1];
	}
	//dp,循环轮次
	for(int i=2;i<=n;i++){
		//换牌次数
		for(int j=0;j<i;j++){
			//当前出牌
			for(int k=0;k<=2;k++){
				int w=pd(c[i],k);//比较是否获胜
				int f=w*a[i];//当前 得分
				//如果j=0,对应没有换牌的情况
				//如果j>0,可能换牌,可能没有换牌
				//所有默认没换牌,再和换牌时得分打擂台
				dp[i][j][k]=dp[i-1][j][k]+f;
				if(j>0){
					dp[i][j][k]=max(dp[i][j][k],max(dp[i-1][j-1][(k+1)%3],dp[i-1][j-1][(k+2)%3])+f-b[j]);
				}
			}
		}
	}
	//找第n轮时所有得分中最大值
	int ma=-0x3f3f3f;
	for(int j=0;j<n;j++){
		for(int k=0;k<=2;k++){
			ma=max(ma,dp[n][j][k]);
		}
	}
	cout<<ma;

	return 0;
}

无注释版

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n;
int a[N],b[N],c[N];
int dp[N][N][3];
int pd(int x,int y){
	if(x==y) return 1;
	else if(y-1==x || y+2==x) return 2;
	else return 0;
}
int main( )
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<n;i++) cin>>b[i];
	for(int i=1;i<=n;i++) cin>>c[i];
	memset(dp,-0x3f3f3f,sizeof(dp));
	for(int k=0;k<=2;k++){
		dp[1][0][k]=pd(c[1],k)*a[1];
	}
	for(int i=2;i<=n;i++){
		for(int j=0;j<i;j++){
			for(int k=0;k<=2;k++){
				int w=pd(c[i],k);
				int f=w*a[i];
				dp[i][j][k]=dp[i-1][j][k]+f;
				if(j>0){
					dp[i][j][k]=max(dp[i][j][k],max(dp[i-1][j-1][(k+1)%3],dp[i-1][j-1][(k+2)%3])+f-b[j]);
				}
			}
		}
	}

	int ma=-0x3f3f3f;
	for(int j=0;j<n;j++){
		for(int k=0;k<=2;k++){
			ma=max(ma,dp[n][j][k]);
		}
	}
	cout<<ma;

	return 0;
}
posted @ 2026-08-22 15:17  陈晨2011  阅读(7)  评论(0)    收藏  举报