题意: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; } }