hdu4283_动态规划

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4283

题目:有一个队列,每个人有一个愤怒值D,如果他是第K个上场,不开心指数就为(K-1)*D。但是边上有一个小黑屋(其实就是个堆栈),可以一定程度上调整上场程序

解题思路 :

dp[i][j]表示区间[i,j]的最小总不开心值

把区间[i,j]单独来看,则第i个人可以是第一个出场,也可以是最后一个出场(j-i+1),也可以是在中间出场(1   ~  j-i+1)

不妨设他是第k个出场的(1<=k<=j-i+1),那么根据栈后进先出的特点,以及题目要求原先男的是排好序的,那么::

第  i+1  到 i+k-1  总共有k-1个人要比i先出栈,

第 i+k   到j 总共j-i-k+1个人在i后面出栈

举个例子吧:

有5个人事先排好顺序  1,2,3,4,5

入栈的时候,1入完2入,2入完3入,如果我要第1个人第3个出场,那么入栈出栈顺序是这样的:

1入,2入,3入,3出,2出,1出(到此第一个人就是第3个出场啦,很明显第2,3号人要在1先出,而4,5要在1后出)

这样子, 动态转移方程 就出来啦,根据第i个人是第k个出场的,将区间[i,j]分成3个部分

 

dp[i][j]=min(dp[i][j],dp[i+1,i+k-1]+dp[i+k,j]+(k-1)*a[i]+(sum[j]-sum[i+k-1])*k);   

 

(sum[j]-sum[i+k-1])*k 表示 后面的 j-i-k+1个人是在i后面才出场的,那么每个人的不开心值都会加个 unhappy,sum[i]用来记录前面i个人的总不开心值,根据题目,每个人的unhappy是个 累加的过程 ,多等一个人,就多累加一次

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <ctime>
 8 #include <queue>
 9 #include <list>
10 #include <set>
11 #include <map>
12 using namespace std;
13 #define INF 0x3f3f3f3f
14 typedef long long LL;
15 
16 int a[110], sum[110], dp[110][110];
17 int dfs(int l, int r)
18 {
19     int res = INF;
20     if(dp[l][r] >= 0)
21         return dp[l][r];
22     if(l>=r)
23         return 0;
24     for(int i = l; i <= r; i++)//a[l]被换到a[i]处,自己举个例子就好了
25     {
26         res = min(res,dfs(l+1,i)+dfs(i+1,r)+a[l]*(i-l)+(sum[r]-sum[i])*(i-l+1));
27     }
28     dp[l][r] = res;
29     return res;
30 }
31 int main()
32 {
33     int t, n;
34     scanf("%d", &t);
35     for(int ca = 1; ca <= t; ca++)
36     {
37         scanf("%d", &n);
38         sum[0] = 0;
39         for(int i = 1; i <= n; i++)
40         {
41             scanf("%d", &a[i]);
42             sum[i] = sum[i-1] + a[i];
43         }
44         memset(dp, -1, sizeof(dp));
45         printf("Case #%d: %d\n", ca, dfs(1, n));
46     }
47     return 0;
48 }
View Code

 

posted @ 2016-09-26 22:22  海无泪  阅读(107)  评论(0编辑  收藏  举报