あなたはワンHDUです - 4283区间DP

長い時間のために読んで、またはブログの首長を参照するためにタイトルを読み始めた
https://blog.csdn.net/codeswarrior/article/details/81479291
巨根ワイヤーのグループ、各ワイヤ巨根巨根ワイヤーが値を持っている、K彼の最初のプレイであれば、値[I] *(K-用コック線 1)、 K-1彼の前に個々の前段ため、少数の人々がスタックとして暗い部屋でのように進めることができ、暗い室内に引き込ま調整することができます最後の人は、出てくるように最小コックワイヤーの最終合計値

//定义dp[i][j]表示原序列区间[i,j]的人的最小屌丝值
//枚举一个中间变量k,设i在区间[i,j]中是第k个上场的
//这样区间分成了两部分
//dp[i+1][i+k-1](k-1个人在i之前),dp[i+k][j](之后的人)
//也就是让[i,i+k-1]这些人进入小黑屋
//i先进的,那么他前面将有k-1个人
//他是第k个上场的,之后再让后面的[i+k,j]这些人上场
//这样很明显i等待了k-1个人屌丝值增长为(k-1)×a[i],而[i+k,j]这些人则等待了k个人,屌丝值增长为k×(这些人的屌丝值之和)
//因此状态转移公式为
//dp[i][j]=min(dp[i][j],dp[i+1][i+k-1]+dp[i+k][j]+k×(sum[j]-sum[i+k-1])+a[i]×(k-1))
//sum[]记录了每个人屌丝值的前缀和
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
int n,a[105],sum[105],dp[105][105];
int main() {
    int t,cas = 0;
    scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        memset(sum,0,sizeof(sum));
        for(int i = 1; i <= n; i++) {
            scanf("%d",&a[i]);
            sum[i] = sum[i-1] + a[i];
        }
        memset(dp,0,sizeof(dp));
        for(int i = 1; i <= n; i++) {
            for(int j = i + 1; j <= n; j++) {
                dp[i][j] = INF;
            }
        }
        //区间长度 
        for(int l = 1; l < n; l++)
            //左端点,      右端点 
            for(int i = 1; i + l <= n; i++) {
                //右端点 
                int j = i + l;
                //枚举中间量,第几个上场 
                for(int k = 1; k <= j - i + 1; k++) 
                    dp[i][j] = min(dp[i][j],dp[i+1][i+k-1]+dp[i+k][j]+k*(sum[j]-sum[i+k-1])+a[i]*(k-1));
            }
        
        printf("Case #%d: %d\n",++cas,dp[1][n]);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/QingyuYYYYY/p/12470257.html