zoukankan      html  css  js  c++  java
  • 洛谷 P1880 [NOI1995] 石子合并(区间DP)

    传送门

    https://www.cnblogs.com/violet-acmer/p/9852294.html

    题解:

      这道题是石子合并问题稍微升级版

      这道题和经典石子合并问题的不同在于,经典的石子合并问题是一排,而此问题是一个圈,也就意味着最后一堆石子可已选择第一堆石子,那这要怎么做呢?

      其实方法很简单,在n堆石子后额外增加(n-1)堆石子,这(n-1)堆石子不是随意造的,其个数与前(n-1)堆石子一一对应。

      然后,就是经典的石子合并问题了。

      对于 1 到 2*n-1堆石子,进行区间最优解的查找即可。

      详情请看大佬博客:https://blog.csdn.net/u013512086/article/details/54565572

    AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 #define INF 0x3f3f3f
     6 #define mem(a,b) memset(a,b,sizeof(a))
     7 const int maxn=200+50;
     8 
     9 int n;
    10 int a[maxn];
    11 int dp[maxn][maxn];//dp[i][j]:讲区间[i,j]堆石子合并所需的最小(或大)的花费
    12 int sum[maxn];//前缀和
    13 
    14 void Solve()
    15 {
    16     //求解最小花费
    17     mem(dp,INF);
    18     for(int i=1;i <= 2*n;++i)
    19         dp[i][i]=0;
    20     for(int len=2;len <= n;++len)
    21     {
    22         for(int i=1;i <= 2*n-len;++i)
    23         {
    24             int j=i+len-1;
    25             for(int k=i;k < j;++k)
    26                 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
    27         }
    28     }
    29     int minRes=INF;
    30     for(int i=1;i <= n;++i)
    31         minRes=min(minRes,dp[i][i+n-1]);
    32     printf("%d
    ",minRes);
    33     //求解最大花费
    34     mem(dp,0);
    35     for(int len=2;len <= n;++len)
    36     {
    37         for(int i=1;i <= 2*n-len;++i)
    38         {
    39             int j=i+len-1;
    40             for(int k=i;k < j;++k)
    41                 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
    42         }
    43     }
    44     int maxRes=0;
    45     for(int i=1;i <= n;++i)
    46         maxRes=max(maxRes,dp[i][i+n-1]);
    47     printf("%d
    ",maxRes);
    48 }
    49 int main()
    50 {
    51     scanf("%d",&n);
    52     mem(sum,0);
    53     for(int i=1;i <= n;++i)
    54         scanf("%d",a+i),a[n+i]=a[i];
    55     for(int i=1;i <= 2*n;++i)
    56         sum[i]=sum[i-1]+a[i];
    57     Solve();
    58 }
    View Code

        

  • 相关阅读:
    OBV15 案例2
    OBV_X3
    涨停板割韭菜走势
    谁有stanford ner训练语料
    CUDA从入门到精通
    MatLab 2014a编译jar包时mcc无法使用的问题
    安装office2013时弹出microsoft setup bootstrapper已停止工作,接着就不能安装了
    Lingo 做线性规划
    C# 连接Paradox DB
    Numpy 数组的切片操作
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9873578.html
Copyright © 2011-2022 走看看