You Are the One
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6706 Accepted Submission(s): 3339
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)
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
Source
Recommend
liuyiding
昨天入门区间dp感觉简单的一批,今天推转移方程都推的快睡着了,其实这题也是一道很模版的区间dp,我们走一遍思路,不感兴趣的可以跳过这一段。
要解决的问题是什么?
给定一个数列,让你每次删除其中的一个数,删除这个数的代价为它和左右的乘积,最后要将数列中除了首尾的数字全都删完,问最小代价。
这题一看,每次要删一个数,然后删除这个数的代价为它和左右两个数的乘积,一看就知道,数删除的顺序会影响最后的结果,但是我们不可能枚举每个删除数的顺序,所以我们可以发现,当一个数被删除之后,它左边的数在删除的时候会乘它右边的数,也就是说枚举任意三个数的乘法,只需要满足这三个数之间的所有数字都被删除即可,所以我们用dp[ i ][ j ]表示区间(i, j)的数字都被删除的最小代价。那么很容易可以看出是个区间dp了。
也就是一般套路,第一层枚举区间长度len,第二层枚举区间起点 i ,第三层枚举断点 k,我们可以知道我们枚举区间的终点 j 为i + len,所以就可以得到状态转移方程为dp[ i ][ j ] = min(dp[ i ][ k ] + dp[ k ][ j ] + val[ i ] * val[ k ] * val[ j ], dp[ i ][ j ])。
所以你知道如何判断一个题是否是区间dp了么?
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 100 + 5, inf = 0x3f3f3f3f; 7 8 int n, value[maxn]; 9 10 int dp[maxn][maxn]; 11 12 int main() { 13 scanf("%d", &n); 14 for(int i = 1; i <= n; i ++) { 15 scanf("%d", &value[i]); 16 } 17 for(int len = 2; len < n; len ++) { 18 for(int i = 1; i + len <= n; i ++) { 19 int j = i + len; 20 dp[i][j] = inf; 21 for(int k = i + 1; k < j; k ++) { 22 dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + value[i] * value[k] * value[j]); 23 } 24 } 25 } 26 printf("%d ", dp[1][n]); 27 return 0; 28 }