• uva10891Game of sum


    题意:经典的取石子游戏是这样的:有一堆石子,A、B两个人轮流取,每次取一颗,只能从边上取,每个石子有相应的价值,A、B两人都想使得自己的价值最多,两个人足够聪明,问最后价值分别是多少

    本题则是可以取多颗,但仍然只能从一侧取得

    分析:状态转移方程

    best[i][j]=sum[i][j]-min(best[i][j-k],best[i+k][j], 0);{1<=k=j-i+1}.

    使用了记忆化的方法,O(n3),书上说有进一步的优化,不过当前数据下已经很快了(64ms)

    代码:

    View Code
     1 #include <stdio.h>
     2 #include <iostream>
     3 #include <string.h>
     4 using namespace std;
     5 const int MAXN = 100 + 10;
     6 #define DEBUG
     7 int min(int a, int b){
     8     return a<b?a:b;
     9 }
    10 int s[MAXN], a[MAXN], d[MAXN][MAXN], vis[MAXN][MAXN], n;
    11 int dp(int i, int j){
    12     if(vis[i][j]) return d[i][j];
    13     vis[i][j]=1;
    14     int m=0, k;
    15     for(k=i+1; k<=j; k++) m=min(m, dp(k, j));
    16     for(k=i; k<j; k++) m=min(m, dp(i, k));
    17     d[i][j]=s[j]-s[i-1]-m;;
    18     return d[i][j];
    19 }
    20 int main(){
    21 #ifndef DEBUG
    22     freopen("in.txt", "r", stdin);
    23 #endif
    24     while(scanf("%d", &n)!=EOF && n){
    25         s[0]=0;
    26         int i;
    27         for(i=1; i<=n; i++){
    28             scanf("%d", &a[i]);
    29             s[i] = s[i-1] + a[i];
    30         }
    31         memset(vis, 0, sizeof(vis));
    32         printf("%d\n", 2*dp(1,n)-s[n]);
    33     }
    34     return 0;
    35 }
    Greatness is never a given, it must be earned.
  • 相关阅读:
    【[USACO08FEB]酒店Hotel】
    【[USACO15JAN]草鉴定Grass Cownoisseur】
    【[USACO09DEC]牛收费路径Cow Toll Paths】
    【[HAOI2009]逆序对数列】
    【Hankson 的趣味题】
    【开车旅行】
    【[ZJOI2006]物流运输】
    【[HNOI2005]狡猾的商人】
    【愤怒的小鸟】
    【[HNOI2015]菜肴制作】
  • 原文地址:https://www.cnblogs.com/zjutzz/p/2911230.html
Copyright © 2020-2023  润新知