CF1167F Solution
题解
⭐:\(inf\)若需多次加减不宜过大,容易溢出。
dp题呐~
状态:\(dp[i][j]\)表示前\(i\)轮距离上次(包括当前卡牌)触发双倍已经经过\(j\)张卡时的最大伤害。
初始值:\(dp[i][j]=inf,dp[i][0]=0\quad (0\le i\le n,1\le j\le 9)\)
转移方程:设\(x1,x2,x3\)分别为\(c=1\)卡牌的最大、次大、第三大\(d\)值,\(y,z\)分别为\(c=2,3\)卡牌的最大\(d\)值。
\[dp[i][j]=dp[i-1][j]\\
dp[i][(j+3)\%10]=max(dp[i][(j+3)\%10],dp[i-1][j]+x1*2+x2+x3)\quad (j\ge 7)\\
dp[i][j+3]=max(dp[i][j+3],dp[i-1][j]+x1+x2+x3)\quad (j<7)\\
dp[i][(j+2)\%10]=max(dp[i][(j+2)\%10],dp[i-1][j]+max(x1*2+x2,x1*2+y,y*2+x1))\quad (j\ge 8)\\
dp[i][j+2]=max(dp[i][j+2],dp[i-1][j]+max(x1+x2,y+x1))\quad (j<8)\\
dp[i][0]=max(dp[i][0],dp[i-1][j]+max(x1,max(y,z))*2)\quad (j=9)\\
dp[i][j+1]=max(dp[i][j+1],dp[i-1][j]+max(x1,y,z))\quad (j<9)\\
(1\le i\le n,9\ge j\ge 0)
\]
好长,但基本思路就是1行为不选的转移方程,2,4,6行为触发双倍时的方程,其余为普通转移。注意\(j\)需倒序枚举,否则会从当前回合的状态转移而来。
目标状态:\(max_{i=0}^{i\le 9} dp[n][i]\)
AC代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10,inf=0x7fffffff;
struct node {int c,d;} a[N];
int dp[N][15];
signed main()
{
int n,k,ans=0;
scanf("%lld",&n);
//初始化
for(int i=0;i<=n;i++)
for(int j=0;j<=9;j++) dp[i][j]=-inf;
for(int i=0;i<=n;i++) dp[i][0]=0;
//dp
for(int i=1;i<=n;i++)
{
scanf("%lld",&k);
for(int j=1;j<=k;j++) scanf("%lld%lld",&a[j].c,&a[j].d);
//贪心求出x1,x2,x3,y,z
int x1=-inf,x2=-inf,x3=-inf,y=-inf,z=-inf;
for(int j=1;j<=k;j++)
{
if(a[j].c==1)
{
if(a[j].d>x1) x3=x2,x2=x1,x1=a[j].d;
else if(a[j].d>x2) x3=x2,x2=a[j].d;
else if(a[j].d>x3) x3=a[j].d;
}
else if(a[j].c==2) y=max(y,a[j].d);
else z=max(z,a[j].d);
}
//转移
for(int j=9;j>=0;j--) dp[i][j]=dp[i-1][j];
for(int j=9;j>=0;j--)
{
if(j>=7) dp[i][(j+3)%10]=max(dp[i][(j+3)%10],dp[i-1][j]+x1*2+x2+x3);
else dp[i][j+3]=max(dp[i][j+3],dp[i-1][j]+x1+x2+x3);
if(j>=8) dp[i][(j+2)%10]=max(dp[i][(j+2)%10],dp[i-1][j]+max(x1*2+x2,max(x1*2+y,y*2+x1)));
else dp[i][j+2]=max(dp[i][j+2],dp[i-1][j]+max(x1+x2,y+x1));
if(j==9) dp[i][0]=max(dp[i][0],dp[i-1][j]+max(x1,max(y,z))*2);
else dp[i][j+1]=max(dp[i][j+1],dp[i-1][j]+max(x1,max(y,z)));
}
}
//统计答案
for(int i=0;i<=9;i++) ans=max(ans,dp[n][i]);
printf("%lld",ans);
return 0;
}