HDU 4283 You Are the One(区间)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4283

题意:有n个人排成一排要上台表演,每个人有一个屌丝值pi。第i个上台表演的人,他的不满意度为(i-1)*pi。

现在有一个类似于栈的黑屋子,你可以让某些人进入这个黑屋子。这些人要按照排的顺序来,那么对于排在最前面的人,

就有两个选择:

(1)让他直接上台表演;

(2)让他暂时进黑屋子。

现在请你选择一个合理的调度顺序,使得最后的总不满意度最小?

 

思路:sum1[i]表示前i个人的屌丝值之和,sum2[i][j]表示从第i个人到第j个人逆序上台的不满意度之和,f[i][j]表示

第i个人到第j个人首先上台的不满意度之和,那么转移的时候将[i,j]这个区间分为两部分[i,k],[k+1,j],那么就有两种选择:

(1)前一部分人先上台:X=f[i][k]+f[k+1][j]+(sum1[j]-sum1[k])*(k-i+1);

(2)后一部分人先上台:Y=f[k+1][j]+sum2[i][k]+(sum1[k]-sum1[i-1])*(j-k).

f[i][j]=min(X,Y)(i<=k<j)。

View Code 

 #include <iostream>

 #include <cstdio>

 #include <cstring>

 #define INF 0x3f3f3f3f

 #define min(x,y) ((x)<(y)?(x):(y))

 using namespace std;

 

 

 int f[105][105],sum1[105],sum2[105][105],n,C,num=0;

 int a[105];

 

 int main()

 {

     for(scanf("%d",&C);C--;)

     {

         scanf("%d",&n);

         int i,j,k,len,x,y;

         for(i=1;i<=n;i++) scanf("%d",&a[i]);

         sum1[0]=0;

         for(i=1;i<=n;i++) sum1[i]=sum1[i-1]+a[i];

         for(i=1;i<=n;i++) for(j=i;j<=n;j++)

         {

             sum2[i][j]=0;

             for(k=j-1;k>=i;k--) sum2[i][j]+=a[k]*(j-k);

         }

         memset(f,INF,sizeof(f));

         for(i=1;i<=n;i++) f[i][i]=0;

         for(len=2;len<=n;len++) for(i=1;i+len-1<=n;i++)

         {

             j=i+len-1;

             for(k=i;k<j;k++)

             {

                 x=f[i][k]+f[k+1][j]+(sum1[j]-sum1[k])*(k-i+1);

                 y=f[k+1][j]+sum2[i][k]+(sum1[k]-sum1[i-1])*(j-k);

                 f[i][j]=min(f[i][j],min(x,y));

             }

         }

         printf("Case #%d: %d\n",++num,f[1][n]);

     }

     return 0;

 }

  

你可能感兴趣的:(HDU)