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;
}

浙公网安备 33010602011771号