zoukankan      html  css  js  c++  java
  • bzoj2017[Usaco2009 Nov]硬币游戏*

    bzoj2017[Usaco2009 Nov]硬币游戏

    题意:

    初始时,一个有N枚硬币的堆栈放在地上,每枚硬币都有一个价值。开始玩游戏时,第一个玩家可以从堆顶拿走一枚或两枚硬币。之后每一轮中,当前的玩家至少拿走一枚硬币,至多拿走对手上一次所拿硬币数量的两倍。当没有硬币可拿时,游戏结束。 两个玩家都希望拿到最多钱数的硬币。求第一个玩家最多能拿多少钱。n≤2000。

    题解:

    首先有dp方程:f[i][j][0]=max(f[i][k][1]+sum(i-k,i)),1≤k≤min(j*2,i),f[i][j][1]=min(f[i][k][0]),1≤k≤min(j*2,i)。

    然而这样会超时。发现所以f[i][k][1]的最大值实际上是f[i][j*2][1]、f[i][j*2-1][1]、f[i][j-1][0]的最大值,f[i][k][0]的最小值也是f[i][j*2][0]、f[i][j*2-1][0]、f[i][j-1][1]的最小值。故可以把dp优化到O(n^2)可过。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(int i=j;i<=k;i++)
     5 #define maxn 2010
     6 using namespace std;
     7 
     8 inline int read(){
     9     char ch=getchar(); int f=1,x=0;
    10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    11     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    12     return f*x;
    13 }
    14 int a[maxn],sm[maxn],f[maxn][maxn][2],n;
    15 int main(){
    16     n=read(); inc(i,1,n)a[i]=read(); for(int i=n;i>=1;i--)sm[n-i+1]=sm[n-i]+a[i];
    17     inc(i,1,n)
    18         inc(j,1,n){
    19             f[i][j][0]=j>1?f[i][j-1][0]:0; int k;
    20             k=2*j-1; if(k<=i)f[i][j][0]=max(f[i][j][0],f[i-k][k][1]+sm[i]-sm[i-k]);
    21             k=2*j;  if(k<=i)f[i][j][0]=max(f[i][j][0],f[i-k][k][1]+sm[i]-sm[i-k]);
    22             f[i][j][1]=j>1?f[i][j-1][1]:0x3fffffff;
    23             k=2*j-1; if(k<=i)f[i][j][1]=min(f[i][j][1],f[i-k][k][0]);
    24             k=2*j; if(k<=i)f[i][j][1]=min(f[i][j][1],f[i-k][k][0]);
    25         }
    26     printf("%d",f[n][1][0]); return 0;
    27 }

    20160830

  • 相关阅读:
    内容生成器.计数器及多列
    STT-MTJ(自旋转移矩磁隧道结)模型的Verilog-A语言描述(仅参考)
    将进酒-唐·李白
    三十六计、孙子兵法
    Keil新建工程步骤
    No.6 Verilog 其他论题
    2-4 Numpy+Matplotlib可视化(二)
    2-3 Numpy+Matplotlib可视化(一)
    0-0 列表,元组,字典,集合
    2-2 Numpy-矩阵
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5838077.html
Copyright © 2011-2022 走看看