E - Greedy Ant
Grice题解最开始看不懂神的思路,还评论请教了一波应该是个集训队大佬QaQ
snuke在当前轮直接选取,那么状态会非常不好记录 我们保留snuke在之前轮,选择放弃暂时不选的次数,然后等蚂蚁走到这来了再选
虽然这个跟原游戏不同,但显然其不会优于最优解,也包含最优解
状态表示:
f
l
,
r
,
k
f_{l,r,k}
fl,r,k开区间
(
l
,
r
)
(l,r)
(l,r)内的糖果已经被取走了,
snuke
\text{snuke}
snuke还能选择
k
k
k次的最优解
状态转移:
- 满足 k > 0 k>0 k>0,那么 snuke \text{snuke} snuke可以选择 l l l或者 r r r,则分别转移到 f l − 1 , r , k − 1 + a l f_{l-1,r,k-1}+a_l fl−1,r,k−1+al和 f l , r + 1 , k − 1 + a r f_{l,r+1,k-1}+a_r fl,r+1,k−1+ar
- 目前 snuke \text{snuke} snuke不选择,则对手选择那么用 f l − 1 , r , k + 1 f_{l-1,r,k+1} fl−1,r,k+1或者 f l , r + 1 , k + 1 f_{l,r+1,k+1} fl,r+1,k+1转移(按照题意,这里转移固定,取 a l , a r a_l,a_r al,ar较大的一个)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=410;
int n;
ll f[N][N][N],a[N];
ll dp(int l,int r,int k)
{
if(f[l][r][k]!=-1) return f[l][r][k];
ll &ans=f[l][r][k];
ans=0;
if(l>=1)
{
if(k) ans=max(ans,a[l]+dp(l-1,r,k-1));
if(a[l]>a[r]) ans=max(ans,dp(l-1,r,k+1));
}
if(r<=n)
{
if(k) ans=max(ans,a[r]+dp(l,r+1,k-1));
if(a[r]>a[l]) ans=max(ans,dp(l,r+1,k+1));
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
memset(f,-1,sizeof f);
for(int i=0;i<=n;i++)
cout<<dp(i,i+1,1)<<'\n';
return 0;
}
上述博客博主太热心了,并且讲的非常详细,以至于题解总结基本都是抄的~~