hdu-4283 You Are the One 区间dp,

题意:n个人排队上台,每个人有一屌丝值D,他的不满意值=D*(k-1)(k为他前面的总人数)。 求整个队列不满意值之和的最小值。你只有一个操作,就是把队首的人塞进小黑屋,也就是压入栈中,后面的人就被提前了。

题解:首先考虑压入栈的性质:对于第1个人,他可以任意第几位上台。若他是第k个上台,则2~k必定 已经上台(因为这些人要么直接上台,要么压在1号上面),所以K+1~n一定还没上台。于是1~n的不满意值便被分解成了两个子问题:(2~k的不满意值)+(K+1~n的不满意值)+第一个人的不满意值。 然后就能递归求解,顺便加上记忆dp。

坑:dp()写成dp[][],vs无法读入样例????

ac代码:

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstring>
#include<algorithm>
using namespace std;
const int maxn = 105;
const int INF = 0x3f3f3f3f;
int ds[maxn];
int d[maxn][maxn];
int sum[maxn];
int dp(int L, int R) {
    if (L >= R) return 0;
    if (d[L][R] != -1)return d[L][R];
    d[L][R] = INF;
    for (int i = L; i <= R; i++) d[L][R] = min(d[L][R], dp(L + 1,i) + ds[L] * (i - L) + dp(i+1,R) + (sum[R] - sum[i])*(i - L + 1));
    return d[L][R];
}
int main() {
    int t;
    cin >> t; int kase = 1;
    while (t--) {
        int n;
        memset(d, -1, sizeof(d));
        cin >> n;
        for (int i = 1; i <= n; i++) {
             scanf("%d", &ds[i]);
        }
        for (int i = 1; i <= n; i++) {
            sum[i] = sum[i - 1] + ds[i];
        }
        printf("Case #%d: ", kase++);
        cout << dp(1, n)<<endl;
    }
}
成功的路并不拥挤,因为大部分人都在颓(笑)
原文地址:https://www.cnblogs.com/SuuT/p/8580556.html