• 51nod1021(区间dp)


    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1021

    题意:中文题诶~

    思路:区间dp

    我们用num[i]存储前i个元素的和,用dp[i][j]存储合并从第i个到第j个元素的代价,那么有动态转移方程式为:

    dp[i][j]=min(dp[i][j], dp[i][k]+dp[k+1][j]+num[j]-num[i-1]);

    还有一个问题:如果我们直接枚举i, j的话有可能我们在计算dp[i][j]时dp[k+1][j]还没计算出来,这样我们自然不能得到正确答案咯.

    其实我们只要换个思路就能解决这个问题啦,我们枚举len, 和i,len表示当前合并的区间长度为len,那么j=i+len-1.

    这样就不会有上面的问题啦,因为区间i,k和区间k+1,j的长度一定小于区间i, j的长度,即在计算dp[i][j]之前我们已经计算出dp[i][k]和dp[k+1][j]啦.

    代码:

     1 #include <bits/stdc++.h>
     2 #define MAXN 110
     3 using namespace std;
     4 
     5 int a[MAXN], num[MAXN], dp[MAXN][MAXN]; //***dp[i][j]存储第i堆到第j堆的合并代价
     6 const int inf=0x3f3f3f3f;
     7 
     8 int main(void){
     9     int n, ans=0;
    10     cin >> n;
    11     for(int i=1; i<=n; i++){
    12         cin >> a[i];
    13         num[i]=num[i-1]+a[i];
    14     }
    15     for(int len=2; len<=n; len++){
    16         for(int i=1; i<n; i++){
    17             int j=i+len-1;  //***这里要注意j可能会大于n
    18             if(j<=n){
    19                 dp[i][j]=inf;
    20                 for(int k=i; k<j; k++){
    21                     dp[i][j]=min(dp[i][j], dp[i][k]+dp[k+1][j]+num[j]-num[i-1]);
    22                 }
    23             }
    24         }
    25     }
    26     cout << dp[1][n] << endl;
    27 }
  • 相关阅读:
    彻悟大师语录
    读书
    复变函数简要
    【洛谷P4781】【模板】拉格朗日插值
    【洛谷P4585】火星商店问题
    【YbtOJ#593】木棍问题
    【YbtOJ#893】带权的图
    【洛谷P4735】最大异或和
    【洛谷P5787】二分图 /【模板】线段树分治
    【ARC098D】Donation
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6322687.html
Copyright © 2020-2023  润新知