[Usaco2010 Dec]Treasure Chest 藏宝箱

题目链接:点这里

Solution:

刚开始以为是博弈论,然而不是。。。

首先考虑n方dp,设f(l,r)为只有\(l\)\(r\)区间的钱的先手最大获利

那么我们可以得到式子f(l,r)=sum(l,r)-min(f(l+1,r),f(l,r-1)),代表取左还是右

代码写出来是这样的:

	for(int j=2;j<=n;j++)
		for(int i=j-1;i>=1;i--)
			f[i][j]=s[j]-s[i-1]-min(f[i+1][j],f[i][j-1]);

不过这道题卡空间,我们可以发现第二维其实可以去掉(相当于滚动数组),然后直接dp

Code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e3+1;
int n,f[N],s[N];
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		f[i]=read();
		s[i]=s[i-1]+f[i];
	}
	for(int j=2;j<=n;j++)
		for(int i=j-1;i>=1;i--)
			f[i]=s[j]-s[i-1]-min(f[i+1],f[i]);
	printf("%d\n",f[1]);
	return 0;
}
posted @ 2019-05-09 18:00  DQY_dqy  阅读(200)  评论(0编辑  收藏  举报