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

Problem Description

  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


思路:

  • 对本蒟蒻来说真的是一道很难的区间DP,寒假集训正好听了清华dalao讲了思路,这才按思路写了一遍;
  • dp[i][j]表示区间[i, j]的最小总代价;
  • 枚举i~j中的每一个断点k,考虑两种情况:
  1. 先把区间[i,k]入栈并出栈,然后把区间[k+1,j]入栈并出栈;
  2. 先把区间[i,k]入栈,再把[k+1,j]入栈并出栈,最后把区间[i,k]倒序出栈;

之前还需要做两个预处理,求一个sum[i][j]数组代表[i, j]上D的总和,和一个数组g[i][j]代表[i, j]依次入栈后倒序出栈的代价,都可用递推求出;

因此就有了状态转移方程:

dp(i, j) = min{g(i, j), mini<=k<j{dp(i, k)+dp(k+1, j)+sum(k+1, j)*(k-i+1), dp(k+1, j)+g(i, k)+sum(i, k)*(j-k)}}



Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define M(a) memset(a, 0, sizeof(a));
 4 const int MAXN = 100 + 10;
 5 __int64 a[MAXN], dp[MAXN][MAXN], sum[MAXN][MAXN], g[MAXN][MAXN];
 6
 7 int main() {
 8     int T, n, icase = 0;
 9     scanf("%d", &T);
10     while(T--) {
11         M(a);M(dp);M(sum);M(g);
12         scanf("%d", &n);
13         for (int i = 1; i <= n; ++i) scanf("%I64d", &a[i]);
14         for (int i = 1; i <= n; ++i)
15             for (int j = i; j <= n; ++j)
16                 sum[i][j] = sum[i][j-1] + a[j];
17         for (int i = n; i >= 1; --i)
18             for (int j = i; j >= 1; --j)
19                 g[j][i] = g[j+1][i] + (i-j) * a[j];
20         for (int l = 1; l <= n; ++l)
21             for (int i = 1; i + l - 1 <= n; ++i) {
22                 int j = i + l - 1;
23                 dp[i][j] = g[i][j];
24                 for (int k = i; k < j; ++k)
25                     dp[i][j] = min(dp[i][j], min(dp[i][k]+dp[k+1][j]+sum[k+1][j]*(k-i+1), dp[k+1][j]+g[i][k]+sum[i][k]*(j-k)));
26             }
27         printf("Case #%d: %I64d\n", ++icase, dp[1][n]);
28     }
29
30     return 0;
31 }
时间: 2024-10-13 02:25:03

HDU-4283 You Are the One (区间DP)的相关文章

HDU 4283 You Are the One 区间dp

题意: 题意好复杂... 给定n个人,从左到右排好队. 他们依次从左到右离开队伍. 每个人有个权值d 当某个人是第k-th离开队伍的,那么不开心值为 d*(k-1) 有一个操作,对于一个子序列,可以把前面一段翻转. 问最小的不开心值和. #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<vector> #include<q

hdu 4283&quot;You Are the One&quot;(区间DP)

传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题意: 有n个屌丝排成一排,每个屌丝都有一个不开心值a[ i ]( i=1,2,3,.....n ),如果第 i 个屌丝第 k 个上场,那么他的不开心度就是(k-1)*a[ i ]. ∑ni=1(ki-1)*a[i]的最小值,其中ki指的是第i个屌丝第k个上场. 关键条件"the director can put the boy into the dark room temporari

HDU 4283 (第k个出场 区间DP)

http://blog.csdn.net/acm_cxlove/article/details/7964594 http://www.tuicool.com/articles/jyaQ7n http://blog.csdn.net/woshi250hua/article/details/7973824 记忆化搜索(15MS): #include <iostream> #include <string> #include <cstring> #include <cs

hdu 4632 子字符串统计的区间dp

题意:查找这样的子回文字符串(未必连续,但是有从左向右的顺序)个数. 简单的区间dp,哎,以为很神奇的东西,其实也是dp,只是参数改为区间,没做过此类型的题,想不到用dp,以后就 知道了,若已经知道[0,i],推[0,i+1], 显然还要从i+1 处往回找,dp方程也简单: dp[j][i]=(dp[j+1][i]+dp[j][i-1]+10007-dp[j+1][i-1])%10007; 减去中间一段重复的 if(s[i]==s[j])dp[j][i]=(dp[j][i]+dp[j+1][i-

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

题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=4283 Problem Description 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

HDU 5900 QSC and Master (区间DP)

题目链接   http://acm.hdu.edu.cn/showproblem.php?pid=5900 题意:给出序列Ai.key和Ai.value,若当前相邻的两个数Ai.key和Ai+1.key的最大公约数大于1,则可以把这两个数消去,同时消去Ai.value和Ai+1.value,每次消去得到的分数为Ai和Ai+1的value值,问最大可能得分. 注意:当Ai和Ai+1被消去后,Ai-1和Ai+2成为了新的相邻的数.若符合条件则可以继续消去. 思路:很明显是区间DP,但是我比赛中如何也

HDU 5151 Sit sit sit(区间DP)

HDU 5151 Sit sit sit 题目链接 区间DP+组合计数问题,转移方程为,每次选当前区间最后一个放的位置,然后乘上组合数C[区间长度][左区间长度] 代码: #include <cstdio> #include <cstring> typedef long long ll; const ll MOD = 1000000007; const int N = 105; int n, a[N]; ll dp[N][N], C[N][N]; int main() { C[1]

HDU 5396 Expression (MUT#9 区间DP)

[题意]:click here~~ [题目大意]: 给你一个一行包含n(2=<n<=100)个数字的式子,和一个字符串(2=<s<=100),字符串里包含三种运算符号:+,-,*,且s=n-1,也就是说在每两个数字之间,插入n-1个符号,位置已经在输入的时候固定了,现在你要做的就是可以自由安排符号的运算顺序,每轮选择之后,将会得到一个结果,求所有的结果的和 [思路]:区间DP: 先贴一下题解(感觉题解有个地方写错了): 设DP[l][r]:表示区间[l,r]这段里面能形成的答案的总

[hdu contest 2019-07-29] Azshara&#39;s deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法

今天hdu的比赛的第一题,凸包+区间dp. 给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相交但是可以有公共端点. 首先找出凸包,然后把n*n条边和m个圆算点到直线距离验证一下边是否与圆相交存到e[n][n]里. 然后显然是一个dp,但是我开始看错题目了以为不能有公共端点,能有公共端点的情况考虑一下像一个找三角形的过程,就是区间dp. 区间dp有一点妙的地方是最大区间范围是凸包点数而不用+1,因为连

HDU 4283 You Are the One (区间dp)

HDU 4283 题意:有n个男屌丝依次排队要登台,如果某个男屌丝前面排有k个人,则该屌丝很生气,生气程度 = (k-1)*D(D代表屌丝程度).现在有一个小黑屋,小黑屋先进后出,如果把某屌丝放进去,那么他后面的人就能先登台.给出每个人的屌丝程度与原定上台顺序,求怎样利用小黑屋,能够使众屌丝生气程度之和最小,求出最小值. 思路: #define 愤怒值 生气程度 dp[i][j]表示从第i个屌丝到第j个屌丝这段区间的min(sum(愤怒值))(假设只有这j-i+1个屌丝) 那么对于dp[i][j