K.(附加题)蘑菇真的贵,友情价更高(博弈dp)

蘑菇真的贵,友情价更高

Time limit 1000 ms
Description
题目链接https://csustacm.fun/problem/1086
由于提莫为巡逻准备的蘑菇太多了,多余的蘑菇路上种不下,于是他精心挑选了一些蘑菇拜访他的好朋友小炮

提莫的蘑菇一共有n个,对于编号为i的蘑菇魔力值是ai。蘑菇的魔力值越高,小炮就越喜欢。当然因为二人是好朋友,蘑菇魔力值最低也不会小于0

提莫要与小炮分享这些蘑菇,他们制定了一个因吹斯听的分配规则:

两人按1-n的顺序逐个分配每个蘑菇的归属权

对于一个蘑菇,如果这一轮的分配者将这个蘑菇分给自己,那么下一轮分配权将转让给对方

反之,如果分配者将蘑菇分配给对方,下一轮他还将持有分配权

你可能会以为提莫会让着小炮,不你想多了!爱恶作剧的提莫会尽力让小炮所获得的蘑菇的魔力值的总和尽可能小!(友尽警告

请你帮小炮算算,如果小炮先手分配,他所能获得的蘑菇的魔力值之和的最大值会是多少?

注意:提莫和小炮都足够聪明且均采取最优策略

Input

单组输入

第一行输入一个n,代表物品的数量,1 <= n <= 3e5

第二行输入n个数字a1-an,代表这n个蘑菇的魔力值,0 <= ai <= 1e9

Output

一个数字,小炮所能获得的蘑菇的魔力值之和的最大值。

Sample Input 1

2
10 20
Sample Output 1

20
Hint

对于样例1,小炮可以要走第一个蘑菇,提莫拿走第二个蘑菇,小炮的喜爱程度是10
小炮也可以把第一个蘑菇给提莫,继续持有第二个蘑菇的分配权,然后拿走第二个蘑菇喜爱程度是20
所以小炮能拿到蘑菇的最大喜爱程度是20


这题很让人纠结,很像博弈论,当又很明显不是博弈论,只不过带有博弈的思维。我这种蒟蒻肯定是放弃了,不过几个大佬讨论了一下,然后被我听到了emmmm。。。
所谓正难则反。。。所以可以逆推。
我们用dp1[]保存小炮的最大值,dp2[]保存提莫的最大值,sum[]保存后缀和,之后我们只需要关注dp1就行啦,因为 d p 2 [ i ] = s u m [ i ] − d p 1 [ i ] ; dp2[i]=sum[i]-dp1[i]; dp2[i]=sum[i]dp1[i];
而我们的难点也是dp1的公式的推导,这里直接给出:
d p 1 [ i ] = m a x ( d p 2 [ i + 1 ] + a [ i ] , d p 1 [ i + 1 ] ) ; dp1[i]=max(dp2[i+1]+a[i],dp1[i+1]); dp1[i]=max(dp2[i+1]+a[i],dp1[i+1]);
即:将***小炮的此处不拿***和***提莫此处拿***进行对比。而因为每个点总会有人拿,所以要么是小炮拿要么提莫拿。到了最后总是要取最大值的,所以不需要考虑太多,于是,将两个人转化成一个人进行计算就简单了很多

#include <cstdio>
#define max(a,b) (a>b)?a:b
#define ll long long
ll a[300020],dp1[300020],dp2[300020],sum[300020];
int main()
{
	int n;
	scanf ("%d",&n);
	for (int i=1; i<=n; i++) scanf ("%lld",&a[i]);
	for (int i=n; i>=1; i--) sum[i]=sum[i+1]+a[i];
	for (int i=n; i>=1; i--){
		dp1[i]=max(dp2[i+1]+a[i],dp1[i+1]);
		dp2[i]=sum[i]-dp1[i];
	}
	ll ans=max(dp1[1],dp2[1]);
	printf ("%lld\n",ans);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值