题意:
有n个人排队,第i个入场的人x的不愉快度是$D_x*(i-1)$,现在给你n个人在队伍中的位置,
你可以用一个栈让一个人后面的人先进入,问最小的不愉快度是多少。
解法:
考虑注意到用栈调整次序时,如果$x_1$从$l$调整到了$r$的位置,那么如果有$x_2$的位置在$l$,
$r$之间那么一定要满足$l<l_2<=r_2<r$。
这样考虑dp:
$f(i,j)$表示i到j最大可以通过调整减小多少的不愉快度,这样就可以dp了。
(注意在转移不交换的情况下$f(i,j) = max { f(i+1,j), f(i,j-1) }$ 不正确,
因为这样求出来的是一个一个大区间套着小区间的答案,不能表示两个区间相互独立的情况,
应该是$f(i,j) = max { f(i,k)+f(k+1,j) }$)
时间复杂度$O(n^3)$。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 #define N 110 6 7 using namespace std; 8 9 int n,ans; 10 int D[N],f[N][N],S[N]; 11 12 int main() 13 { 14 int T,Te=0; 15 scanf("%d",&T); 16 while(T--) 17 { 18 scanf("%d",&n); 19 S[0]=0; 20 ans=0; 21 for(int i=1;i<=n;i++) 22 { 23 scanf("%d",&D[i]); 24 S[i]=S[i-1]+D[i]; 25 ans+=(i-1)*D[i]; 26 } 27 for(int i=1;i<=n;i++) f[i][i]=0; 28 for(int d=2;d<=n;d++) 29 { 30 for(int i=1;i<=n-d+1;i++) 31 { 32 int j=i+d-1; 33 f[i][j]=0; 34 for(int k=i;k<j;k++) 35 f[i][j] = max(f[i][j], f[i][k]+f[k+1][j]); 36 f[i][j] = max(f[i][j], f[i+1][j]+S[j]-S[i]-D[i]*(j-i)); 37 } 38 } 39 printf("Case #%d: %d ",++Te,ans-f[1][n]); 40 } 41 return 0; 42 }