You Are the One HDU - 4283(区间dp)

题目

The TV shows such as You Are the One has been very popular. In order to meet the need of boys who are still single, TJUT hold the show itself. The show is hold in the Small hall, so it attract a lot of boys and girls. Now there are n boys enrolling in. At the beginning, the n boys stand in a row and go to the stage one by one. However, the director suddenly knows that very boy has a value of diaosi D, if the boy is k-th one go to the stage, the unhappiness of him will be (k-1)*D, because he has to wait for (k-1) people. Luckily, there is a dark room in the Small hall, so the director can put the boy into the dark room temporarily and let the boys behind his go to stage before him. For the dark room is very narrow, the boy who first get into dark room has to leave last. The director wants to change the order of boys by the dark room, so the summary of unhappiness will be least. Can you help him?
Input
  The first line contains a single integer T, the number of test cases. For each case, the first line is n (0 < n <= 100)
  The next n line are n integer D1-Dn means the value of diaosi of boys (0 <= Di <= 100)
Output
  For each test case, output the least summary of unhappiness .
Sample Input

2   
5
1 2 3 4 5
5
5 4 3 2 2

Sample Output

Case #1: 20
Case #2: 24

题意

n个人本来按顺序上台,每个人对应一个等待系数,如果他是第i个上台的那么等待值为(i-1)他的等待系数,现在你可以调整他们的出场顺序,调整方式为完全类似栈的方式,后进的先出去。问总的等待值最小为多少。
设dp[i][j]代表将区间所有人都送上台的最小总等待值(这个最小等待值是以这个区间的人为参考基础,不涉及其它区间,比如dp[3][5],就代表3,4,5这三个人按照某种顺序上台的最小总期待值)
建立转移方程
dp[i][j] = min(dp[i][j], dp[i][k-1] + dp[k+1][j] + (j-i)a[k]+((sum[j] - sum[k])(k-i)));
k代表的是取第k个人作为i~j区间上最后一个出场的人,根据栈的性质,那么 i ~ j区间中i ~ k-1 的人先于第k个人出场,对于dp[i]j]的贡献为 dp[i][k-1]。(之前看了些题解都说是k是第k个上场的,到底是区间的k个,还是答案第k个,真搞不懂是如何想出一样的转移方程的)
而k+1 ~ j的人都得等待i ~ k-1的人上台,dp[k+1][j]的含义是只考虑这个区间的人为参考基础的,那么这个区间的每个人对应到以i~j为参考系的时候其实每个人都等待了k-1-i+1 = k-i个人,所以再加上(sum[j] - sum[k])
(k-i),才是k+1 ~ j的人对答案的贡献, 第k个人对答案的贡献为 (j-i)*a[k],因为他要等这个区间的所有人上场。
由于dp[i][j]都是以自己区间作为参考系的,无后效性,从最大规模dp[1][n]向内存不断缩小规模,是存在最优子结构的,整体最优到局部最优,转移方程合理,确认合理后,才有的正推求解。
对于i == j 时以及 j - i == 1各种实际存在的位置dp设置为0,减少分支判断,对结果无影响。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 102
int const inf = 0x3f3f3f3f;
using namespace std;
int dp[maxn][maxn];
int a[maxn], sum[maxn];
int main(){
	int t, n, i, j, k;
	scanf("%d", &t);
	int  cont = 1;
	while(t--){
		scanf("%d", &n);
		sum[0] = 0;
		for(i = 1; i <= n; i++){
			scanf("%d", &a[i]);
			sum[i] = (sum[i-1]+a[i]);
		}
		memset(dp, 0, sizeof(dp)); 
		for(i = n; i >= 1; i--){
			for(j = i; j <= n; j++){
				if(i == j){
					dp[i][j] = 0;
					continue;
				}
				dp[i][j] = inf;
				for(k = i; k <= j; k++){
					dp[i][j] = min(dp[i][j], dp[i][k-1] + dp[k+1][j] + (j-i)*a[k]+((sum[j] - sum[k])*(k-i)));
				}
			}
		}
		printf("Case #%d: %d\n", cont++,dp[1][n]);
	}	
	return 0;
} 
发布了52 篇原创文章 · 获赞 2 · 访问量 867

猜你喜欢

转载自blog.csdn.net/qq_44714572/article/details/103098404