P10111 [GESP202312 七级] 纸牌游戏 (决策路径DP)
Problem: P10111 [GESP202312 七级] 纸牌游戏

这是我一开始的DP思路:
每个格子 都由前一列的所有状态推导出来
如果在同一行,那么不消耗b[i]
如果不在同一行,消耗b[i]
然后每次操作都取最优值
但是不难发现,这是一个假的解法
因为对于样例1中
第一行第三列的最优解应该为25
这样子的话,第二行第四列的最优值就不会达到200+20-1
那么怎么办呢
于是我想到,多加一层
变成的是在dp[i][j][k]
其中
i:指的是对应的012操作
j:指的是对应的第N次
k:指的是当前消耗了第几个b值改变
那么dp[i][j][k]
就是指在消耗了第k个变换次数后的第j次的第i个手势中所能得到的最高分
因此推出公式:
if(p == 0)
{
if(i == k)
DPa[i][r][p] =max(DPa[i][r][p],DPa[k][r-1][p]+dpa[i][r][p]);
else
{
if(i != k)
DPa[i][r][p] = max(DPa[i][r][p],DPa[k][r-1][p-1]+dp[i][r]-b[p]);
else
{
if(r-1 > p) //如果是同一行传递,一定要注意前一个数字是否有对应的k值层
DPa[i][r][p] = max(DPa[i][r][p],DPa[k][r-1][p]+dp[i][r]);
}
}
}
当时写的代码有点乱
r = j
p = k
其中 注意要将dp数组初始化为-INF,因为可能存在操作使得答案成为负数
Accepted Code:
//P10111
#include <iostream>
#define ll long long
using namespace std;
ll a[1010],b[1010],c[1010];
ll dp[35][1010],Dp[35][1010],DPa[35][1010][1010],dpa[35][1010][1010];
int main()
{
ll N;
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];
}
for(int i=0; i<=2; i++)
{
for(int r=1; r<=N; r++)
{
if(c[r] == 1)
{
if(i == 0) dp[i][r] = 0;
if(i == 1) dp[i][r] = a[r];
if(i == 2) dp[i][r] = 2*a[r];
}
if(c[r] == 2)
{
if(i == 1) dp[i][r] = 0;
if(i == 2) dp[i][r] = a[r];
if(i == 0) dp[i][r] = 2*a[r];
}
if(c[r] == 0)
{
if(i == 2) dp[i][r] = 0;
if(i == 0) dp[i][r] = a[r];
if(i == 1) dp[i][r] = 2*a[r];
}
}
}
for(int i=0; i<=2; i++)
{
for(int r=1; r<=N; r++)
{
for(int k=0; k<=N; k++)
DPa[i][r][k] = -1e9;
dpa[i][r][0] = dp[i][r];
//cout<<dp[i][r]<<" ";
}//cout<<endl;
}
for(int r=1; r<=N; r++)
{
for(int i=0; i<=2; i++)
{
//Dp[i][r]
for(int k=0; k<=2; k++)
{
for(int p=0; p<r; p++)
{
if(p == 0)
{
if(i == k)
{
DPa[i][r][p] =max(DPa[i][r][p],DPa[k][r-1][p]+dpa[i][r][p]);
//cout<<"p == 0 r i k p:"<<r<<" "<<i<<" "<<k<<" "<<p<<" "<<DPa[i][r][p]<<endl;
}
}
else
{
if(i != k)
{
//if(r-1 >= p)
DPa[i][r][p] = max(DPa[i][r][p],DPa[k][r-1][p-1]+dp[i][r]-b[p]);
//cout<<"i != k r i k p:"<<r<<" "<<i<<" "<<k<<" "<<p<<" "<<DPa[i][r][p]<<endl;
}
else
{
if(r-1 > p)
{
DPa[i][r][p] = max(DPa[i][r][p],DPa[k][r-1][p]+dp[i][r]);
//cout<<"i == k r i k p:"<<r<<" "<<i<<" "<<k<<" "<<p<<" "<<DPa[i][r][p]<<endl;
}
}
}
}
}
}
}
ll Max = 0;
for(int i=0; i<=2; i++)
{
for(int r=1; r<=N; r++)
{
for(int k=0; k<=N; k++)
Max = max(Max,DPa[i][r][k]);
//cout<<DPa[i][r]<<" ";
} //cout<<endl;
}
cout<<Max;
return 0;
}
励志故事:


浙公网安备 33010602011771号