hdu 4283 You Are the One(区间dp)

来源:互联网 发布:matlab求解凸优化问题 编辑:程序博客网 时间:2024/05/14 13:12

You Are the One

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 939    Accepted Submission(s): 446


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  512345554322
 

Sample Output
Case #1: 20Case #2: 24
 

Source
2012 ACM/ICPC Asia Regional Tianjin Online
 

Recommend
liuyiding


该文转自:http://blog.csdn.net/woshi250hua/article/details/7973824

题目大意:给定一个序列,序列内的人有屌丝值Di,是第然后将这个序列进栈,第i个人如果是第k个出栈,那么最后的屌丝总值增加Di * (k-1), 求一个出栈序列使得总屌丝值最小。


解题思路:2012年天津网赛的1006题,当时不会做,因为一直想着记录栈里面的状态,也就是谁谁谁在栈里面,然后就想着用bitset什么的,然后就没有然后了.

    言归正传,本题的模型是求一个合法的出栈序列使得屌丝总值最小,需要用区间DP解决之。合法的出栈序列中有一个很重要的性质:[1,n]这是一开始的所有元素,当1第k个出栈时[2,k]肯定比1先出栈,[k+1,n]肯定比1后出栈,正因为只要1才能第k个出栈.。这样一个区间划分成两个子区间[2,k],[k+1,n],就这样递归下去只到区间长度为1.而区间DP正是解决这类区间划分问题的利器,其实区间DP也就是一种思想啦。

    区间DP一般有两种写法,三个for循环或者记忆化搜索,个人觉得记忆化搜索虽然效率低点,但是写起来相当优美。

    本题我写的for循环写法是参照cxlove的写法,把当前选择对后续选择的影响给提前计算了,这也是区间Dp经常用到的技巧。而记忆化搜索写法在搜索的过程中都只考虑当前的影响,因为多了一维,所以可以这样,如果开两维,就必须将后续影响考虑在内了.


测试数据:

InPut:
10
5
1 2 3 4 5

5 4 3 2 2
100
41 67 34 0 69 24 78 58 62 64 5 45 81 27 61 91 95 42 27 36 91 4 2 53 92 82 21 16
18 95 47 26 71 38 69 12 67 99 35 94 3 11 22 33 73 64 41 11 53 68 47 44 62 57 37
59 23 41 29 78 16 35 90 42 88 6 40 42 64 48 46 5 90 29 70 50 6 1 93 48 29 23 84
54 56 40 66 76 31 8 44 39 26 23 37 38 18 82 29 41

OutPut:
Case #1: 20
Case #2: 24
Case #3: 170975

#include<stdio.h>#include<string.h>#define INF 0xffffffint a[105],sum[105],dp[105][105];int MIN(int a,int b){ return a<b?a:b; }int main(){    int T=1,t,i,j,k,l,n,temp;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(sum[0]=0,i=1;i<=n;i++)        {            scanf("%d",a+i);            sum[i]=sum[i-1]+a[i];        }        memset(dp,0,sizeof(dp));        for(i=1;i<=n;i++)            for(j=i+1;j<=n;j++)            dp[i][j]=INF;        for(l=1;l<n;l++)        {            for(i=1;i<=n-l;i++)            {                j=i+l;                for(k=i;k<=j;k++)                {                    temp=dp[i+1][k]+dp[k+1][j]+a[i]*(k-i)+(sum[j]-sum[k])*(k-i+1);                    dp[i][j]=MIN(dp[i][j],temp);                }            }        }        printf("Case #%d: %d\n",T++,dp[1][n]);    }    return 0;}


原创粉丝点击