• USACO 3.3 游戏


    https://www.luogu.org/problemnew/show/P2734

    是道好dp,加深了我对区间dp的理解

    一开始可以有思路:f[i][j]表示区间i-j内,先手的最大得分

    但是转移有困难,因为我在思考第二个人会怎么走

    实际上这是没有必要的,动态规划不考虑所有步的细节,而是从前一种状态转移,至于前一种如何,并不关心

    考虑到,当f[i][j]的人先手取完之后,剩下的就是第二个人,这是可以把他认为是先手

    那么第一个人可能取a[i]或a[j],那剩下的人取的就是f[i + 1][j]或者f[i][j - 1],那么区间i-j的和减第二个人的得分就是第一个人的得分

    时间:1.0h

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    inline int read()
    {
      int ans = 0,op = 1;
      char ch = getchar();
      while(ch < '0' || ch > '9')
        {
          if(ch == '-') op = -1;
          ch = getchar();
        }
      while(ch >= '0' && ch <= '9')
        {
          (ans *= 10) += ch - '0';
          ch = getchar();
        }
      return ans * op;
    }
    const int maxn = 105;
    int n;
    int sum[maxn],a[maxn];
    int f[maxn][maxn];
    /*int dp(int i,int j)
    {
      if(j < i) return 0;
      if(f[i][j]) return f[i][j];
      return f[i][j] = max(sum[j] - sum[i] - dp(i + 1,j),sum[j - 1] - sum[i - 1] - dp(i,j - 1));
      }*/              
    int main()
    {
      n = read();
      for(int i = 1;i <= n;i++)
        a[i] = read(),f[i][i] = a[i];
      for(int i = 1;i <= n;i++)
        sum[i] = sum[i - 1] + a[i];
      for(int i = n - 1;i >= 1;i--)
        for(int j = i + 1;j <= n;j++)
          f[i][j] = max(sum[j] - sum[i - 1] - f[i + 1][j],sum[j] - sum[i - 1] - f[i][j - 1]);
      printf("%d %d",f[1][n],sum[n] - f[1][n]);
    }
  • 相关阅读:
    Java使用printf格式化日期
    Java时间Date类
    Java数组
    Spring Cloud Stream
    Spring Cloud Bus
    Spring Cloud Config
    api服务网关?
    SPRINGBOOT集成SWAGGER2
    MySQL锁(一)全局锁:如何做全库的逻辑备份?
    Spring的FactoryBean
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/10048200.html
Copyright © 2020-2023  润新知