hdu4283 You Are the One

传送门

题目

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 .

题目大意

有n个人,输入n个基值(愤怒值)v[],表示每个人的愤怒值,现在他们依次上台表演,如果i是第k个上台,那么他的愤怒值为(k-1)*v[i]  现在有一个栈,可以让一些人进栈,让后面的人先上台表演,这样可以改变部分顺序,求所有人最小的愤怒值和。

分析

用dpij表示i到j区间的人的最小值,我们枚举考虑的区间的长度和起点,并枚举这段区间的第一个人是在第几个登场,注意特判这个人第一个和最后一个登场的情况。为了集体后移时的计算方便,我们记录一个前缀和。具体转移方程等见代码。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int dp[110][110],sum[1100],v[1100];
int main()
{     int n,m,i,j,k,t,p;
      scanf("%d",&t);
      for(p=1;p<=t;p++){
          scanf("%d",&n);
          sum[0]=0;
          for(i=1;i<=n;i++){
            scanf("%d",&v[i]);
            sum[i]=sum[i-1]+v[i];
            dp[i][i]=0;
        }
          for(i=1;i<n;i++)
            for(j=1;j+i<=n;j++){
                dp[j][j+i]=min(sum[j+i]-sum[j]+dp[j+1][j+i],dp[j+1][j+i]+v[j]*i);
            for(k=2;k<=i;k++)
              dp[j][j+i]=min(dp[j][j+i],dp[j+k][j+i]+dp[j+1][j+k-1]+v[j]*(k-1)+(sum[j+i]-sum[j+k-1])*k);
          }
        printf("Case #%d: %d\n",p,dp[1][n]);
      }
      return 0;
}
posted @ 2018-06-19 14:13  水题收割者  阅读(261)  评论(0编辑  收藏  举报