zoukankan      html  css  js  c++  java
  • luogu P1880 [NOI1995]石子合并 区间DP

    这么水的题不想水博客来着,但是感觉这种把原序列倍增后,进行区间DP的思路很奇妙,记录一下。

    因为是一个环,所以对原序列倍增后,再进行DP,最后枚举起始位置。

    dp[i][j]表示[i,j]这一段合并产生的最大/最小价值。

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 typedef long long ll;
     5 int n;
     6 ll vec[220],res[2];
     7 ll dp[220][220][2];
     8 ll dfs(int l,int r,int opt)
     9 {
    10     if (dp[l][r][opt] != 0 || l == r)
    11         return dp[l][r][opt];
    12     if (opt == 0)
    13         dp[l][r][opt] = 100000000000000;
    14     for (int i = l;i <= r - 1;i++)
    15         if (opt == 1)
    16             dp[l][r][opt] = max(dfs(l,i,opt) + dfs(i + 1,r,opt),dp[l][r][opt]);
    17         else
    18             dp[l][r][opt] = min(dfs(l,i,opt) + dfs(i + 1,r,opt),dp[l][r][opt]);
    19     dp[l][r][opt] += vec[r] - vec[l - 1];
    20     return dp[l][r][opt];
    21 }
    22 int main()
    23 {
    24     scanf("%d",&n);
    25     for (int i = 1;i <= n;i++)
    26         scanf("%lld",&vec[i]);
    27     for (int i = n + 1;i <= 2 * n;i++)
    28         vec[i] = vec[i - n];
    29     for (int i = 1;i <= 2 * n;i++)
    30         vec[i] += vec[i - 1];
    31     res[0] = 100000000000000;
    32     for (int i = 1;i <= n + 1;i++)
    33     {
    34         res[0] = min(res[0],dfs(i,i + n - 1,0));
    35         res[1] = max(res[1],dfs(i,i + n - 1,1));
    36     }
    37     printf("%lld
    %lld
    ",res[0],res[1]);
    38     return 0;
    39 }
    心之所动 且就随缘去吧
  • 相关阅读:
    奇迹银桥「1」
    20190729-“退役”专场
    20190727-只是睡着了
    $mathcal{Miemeng}$的病态码风计划
    20190725-Silly
    作业-[luogu4396][AHOI2013]-莫队
    数学网学笔记
    20190722-Moni和Boly的故事
    数学学习笔记
    20190719-FirstZero
  • 原文地址:https://www.cnblogs.com/iat14/p/10565994.html
Copyright © 2011-2022 走看看