You Are the One

题意:

有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\n",++Te,ans-f[1][n]);
40     }
41     return 0;
42 }
View Code

 

posted @ 2017-03-11 11:02  lawyer'  阅读(145)  评论(0编辑  收藏  举报