hdu4283_动态规划
Posted _lm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于hdu4283_动态规划的主要内容,如果未能解决你的问题,请参考以下文章
HDU4283 You Are the One(经典区间dp)