您的位置:首页 > 其它

[bzoj 2017] [Usaco2009 Nov]硬币游戏

2016-06-18 15:19 453 查看
  一个多月没更博客了。。(期间明白了自己有多傻逼。

  这种问题大概就倒着做...

  f[i][j]:表示考虑剩下的硬币i..n,且之前的人取了j个时,先手最多拿到的钱数。aft[i]:表示硬币i..n的总钱数。

  f[i][j]=aft[i]-min{ f[k][k-i] },(i<k<=min(n,i+2*j))

  k随着j的增加而增加。不同的j只是k的范围不同而已。所以记录一波最小值就可以了。

  时间复杂度O(n²)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2023;
int f[maxn][maxn];
int aft[maxn],a[maxn];
int i,j,k,n,m;

int ra;char rx;
inline int read(){
rx=getchar(),ra=0;
while((rx<'0'||rx>'9'))rx=getchar();
while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
}
inline int min(int a,int b){return a<b?a:b;}
int main(){
n=read();
for(i=1;i<=n;i++)a[i]=read();
for(i=n;i;i--)aft[i]=aft[i+1]+a[i];
for(i=n;i;i--)for(j=(n-i+2)>>1;j<=n;j++)f[i][j]=aft[i];int mn;
for(i=n-1;i;i--){
mn=1e9,k=i;
for(j=1;j<=i;j++){
if(k<=n)k++,mn=min(mn,f[k][k-i]);
if(k<=n)k++,mn=min(mn,f[k][k-i]);
f[i][j]=aft[i]-mn;
if(k>n)break;
}
for(j++;j<=i;j++)f[i][j]=aft[i]-mn;
}
printf("%d\n",f[1][1]);
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: