Hdu 4283 You Are the One (区间DP)

题目链接:

  Hdu 4283 You Are the One

题目描述:

  给出n个数,每个数要先进栈然后出栈,第i个出栈的数a,花费的价值是(i-1)*a.问所有的数出栈花费的最小价值是多少?

解题思路:

  额······,区间DP专题里面的题目。区间DP不是唯一的解法,应该也是可行解咯。难点就是在于如何模拟栈的进出,胡乱YY,写了一发也是wa。然后搜了一下题解,发现其实只要调整一下区间Dp时候的策略就好辣。由于要满足出栈的条件,所以只能进行微调。dp[x][y] 表示 区间 [x, y] 上所有的数出栈后的最小花费。那么对于区间 [x, y] 中的数字 a[x],有可能第1个出栈,也有可能最后一个出栈,如果第i个出栈的话前i-1个数字要按照顺序出栈,然后a[x]出栈,[i+1,y]出栈。对于a[x]要加上a[x]*i的花费,对于[i+1, y]要加上sum(i+1, y) * (i-x+2)的额外花费。

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef __int64 LL;
 8 const int INF = 0xfffffff;
 9 const int maxn = 110;
10 LL dp[maxn][maxn], a[maxn], arr[maxn];
11 
12 int main ()
13 {
14     int T, n;
15     scanf ("%d", &T);
16     for (int t=1; t<=T; t++)
17     {
18         scanf ("%d", &n);
19         a[0] = arr[0] = 0;
20         for (int i=1; i<=n; i++)
21         {
22             scanf ("%I64d", &a[i]);
23             arr[i] = arr[i-1] + a[i];
24         }
25 
26         memset (dp, 0, sizeof(dp));
27         for (int l=1; l<n; l++)
28             for (int i=1; i+l<=n; i++)
29             {
30                 int j = i + l;
31                 LL Min = INF;
32                 for (int k=i; k<=j; k++)
33                 {
34                     LL num = a[i]*(k-i) + (arr[j] - arr[k])*(k-i+1) + dp[i+1][k] + dp[k+1][j];
35                     Min = min (Min, num);
36                 }
37                 dp[i][j] = Min;
38             }
39         printf ("Case #%d: %I64d\n", t, dp[1][n]);
40     }
41     return 0;
42 }
43 /*
44 2
45 5
46 1
47 2
48 3
49 4
50 5
51 5
52 5
53 4
54 3
55 2
56 2
57 */

 

posted @ 2015-11-03 10:12  罗茜  阅读(822)  评论(0编辑  收藏  举报