hdu 4283 You Are the One 区间dp

 

参考了别人的思路

dp[i][j]表示从第i个人到第j个人这段区间的最小花费是只考虑这j-i+1个人,不需要考虑前面有多少人)那么对于dp[i][j]的第i个人,、就有可能第1个上场,也可以第j-i+1个上场。考虑第K个上场即在i+1之后的K-1个人是率先上场的,那么就出现了一个子问题 dp[i+1][i+1+k-1-1]表示在第i个人之前上场的对于第i个人,由于是第k个上场的,那么愤怒值便是val[i]*(k-1)其余的人是排在第k+1个之后出场的,也就是一个子问题dp[i+k][j],对于这个区间的人,由于排在第k+1个之后,所以整体愤怒值要加上k(sigma(i+k--j))

为什么若 i是第K个上场就是 i+1之后的K-1个人是率先上场的 因为i是第一个入栈的 到i出栈的时候i也会是栈里的最后一个 此时他是第k个出栈的那肯定就是他后面的K-1个人是率先出栈的咯

 

 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #define maxx 10000002
 5 using namespace std;
 6 
 7 int dp[102][102],a[102],sum[102];
 8 
 9 int solve(int n)
10 {
11     memset(dp,0,sizeof(dp));
12     for(int i=0;i<=n;i++)
13         for(int j=i+1;j<=n;j++)
14             dp[i][j]=maxx;
15 
16     for(int l=2;l<=n;l++)
17     {
18         for(int i=1;i+l-1<=n;i++)
19         {
20             int j=i+l-1;
21             for(int k=1;k<=l;k++)
22                 dp[i][j]=min(dp[i][j],a[i]*(k-1)+dp[i+1][i+k-1]+dp[i+k][j]+k*(sum[j]-sum[i+k-1]));
23         }
24     }
25     return dp[1][n];
26 }
27 
28 int main()
29 {
30      int t,n,m,i,j,p=1;
31      scanf("%d",&t);
32      while(t--)
33      {
34          scanf("%d",&n);
35          memset(sum,0,sizeof(sum));
36          for(i=1;i<=n;i++)
37          {
38              scanf("%d",&a[i]);
39              sum[i]=sum[i-1]+a[i];
40          }
41          printf("Case #%d: %d\n",p++,solve(n));
42      }
43      return 0;
44 }

 

posted @ 2014-05-07 16:08  galaxy77  阅读(150)  评论(0编辑  收藏  举报