HDU 4283 You Are the One(区间dp)

http://acm.hdu.edu.cn/showproblem.php?pid=4283

题意:
有n个人,每个人有个不开心值v,现在排队表演,对于某人来说如果他排在第k个,那么他的不开心值就为(k-1)*v。现在有个小黑屋,相当于栈,可以改变队伍的顺序,计算出最小的不开心值和。

思路:

dp【i】【j】表示从第i个人到第j个人这段区间的最小花费(是只考虑这j-i+1个人,不需要考虑前面有多少人) 

那么对于dp【i】【j】的第i个人,他可以在任何位置上场。现在考虑第K个上场  那么i+1之后的K-1个人是率先上场的,那些人的不开心值就是dp【i+1】【i+k-1】。

对于第i个人,由于是第k个上场的,他的不开心值就是a[i]*(k-1) 。

其余的人是排在第k+1个之后出场的,也就是dp【i+k】【j】,由于他们要等前面的k个人,所有此时不开心值还要额外加上k*(sum【j】-sum【i+k-1】)。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<sstream>
 6 #include<vector>
 7 #include<stack>
 8 #include<queue>
 9 #include<cmath>
10 #include<map>
11 #include<set>
12 using namespace std;
13 typedef long long ll;
14 typedef pair<int,int> pll;
15 const int INF = 0x3f3f3f3f;
16 const int maxn = 100 + 5;
17 
18 int n;
19 int a[maxn];
20 int sum[maxn];
21 int d[maxn][maxn];
22 
23 int main()
24 {
25     //freopen("in.txt","r",stdin);
26     int T;
27     int kase=0;
28     scanf("%d",&T);
29     while(T--)
30     {
31         sum[0]=0;
32 
33         scanf("%d",&n);
34 
35         memset(d,0,sizeof(d));
36         for(int i=1;i<=n;i++)
37         {
38             for(int j=i+1;j<=n;j++)
39                 d[i][j]=INF;
40         }
41 
42         for(int i=1;i<=n;i++)
43         {
44             scanf("%d",&a[i]);
45             sum[i]=sum[i-1]+a[i];
46         }
47 
48         for(int r=2;r<=n;r++)
49         {
50             for(int i=1;i+r-1<=n;i++)
51             {
52                 int j=i+r-1;
53                 for(int k=i;k<=j;k++)
54                 {
55                      d[i][j]=min(d[i][j],d[i+1][k]+d[k+1][j]+a[i]*(k-i)+(sum[j]-sum[k])*(k-i+1));
56                 }
57             }
58         }
59          printf("Case #%d: %d
",++kase,d[1][n]);
60     }
61     return 0;
62 }
原文地址:https://www.cnblogs.com/zyb993963526/p/7217565.html