• you are the one(区间dp)


    传送门

    You Are the One

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


    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    5 1 2 3 4 5 5 5 4 3 2 2
     
    Sample Output
    Case #1: 20 Case #2: 24
     
    【题目大意】
    n个人参加节目,每人都有一个屌丝值D,如果他第k个上场,那么他的不高兴值为(k-1)*D,因为他要等k-1个人。
    节目有个小黑屋(是个栈,满足栈的性质)可以改变入场顺序。求最小不高兴值。
    【思路】
    区间dp。
    现在上场的人的可能性有..栈顶的那个人,队伍中的那个人,队伍中的人进栈后,队首的那个人。
    用dp[i][j]表示第i个人到第j个人的最小不高兴价值。
    区间dp要进行区间合并,进行枚举断点k。
    dp[i][j]由dp[i][k]和dp[k+1][j]转移而来。
    可以第i--k个人先上舞台,k+1--j后上舞台。
    也可以第k+1---j个人先上舞台,第i--k个人后上舞台,这就要求i--k这些人进栈,那么再上舞台的顺序就是原来的逆序,不高兴值预处理。
    注意,对于dp[i][j]是个独立的区间,看成第i个就是这个区间的第一个进行处理。只需在合并时处理一下。
    转移方程:
    dp[i][j]=min(dp[i][j],min{dp[i][k]+dp[k+1][j]+(sum[j]-sum[k-1])*(k-i+1)  ,dp[k+1][j]+v[i][k]+(sum[k]-sum[i-1])*(j-k) }) 
    转移方程指的是在上述两种情况中寻找最小值,其中sum是因为我们在处理dp[i][j]时是将i看做第一个处理的,
    如果说i--k个先进入,k+1--j后进入(第一种情况),k+1--j每个人前面多了k-i+1个人,所以要加上产生的不高兴值。
    记忆化搜索也可做。
    最大值0x7fffffff(7个f为2147483647,3个f五位数)。
    【code】
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define inf 0x7fffffff
    int n,t,kas;
    int sum[110],v[110][110],dp[110][110],a[110];
    void befr() {
        for(int i=1; i<=n; i++)
            for(int j=i-1; j>=1; j--)
                v[j][i]=v[j+1][i]+a[j]*(i-j);
    }
    int main() {
        scanf("%d",&t);
        while(t--) {
            memset(sum,0,sizeof(sum));
            memset(v,0,sizeof(v));
            scanf("%d",&n);
            for(int i=1; i<=n; i++) {
                scanf("%d",&a[i]);
                sum[i]=sum[i-1]+a[i];
            }
            for(int i=0; i<=n; i++)
                for(int j=0; j<=n; j++)
                    if(i!=j)
                        dp[i][j]=inf;
                    else
                        dp[i][j]=0;
            befr();
            for(int j=1; j<=n; j++)
                for(int i=j-1; i>=1; i--)
                    for(int k=i; k<j; k++) {
                        dp[i][j]=min(dp[i][j],min(dp[i][k]+dp[k+1][j]+(sum[j]-sum[k])*(k-i+1),dp[k+1][j]+v[i][k]+(sum[k]-sum[i-1])*(j-k)));
                    }
            printf("Case #%d: %d
    ",++kas, dp[1][n]);
        }
        return 0;
    }
  • 相关阅读:
    wait 和 notify 方法
    synchronized关键字
    多线程之thread、runnable的区别
    CodeForces 213 E
    hdu 3038 并查集
    zoj 3349 dp + 线段树优化
    hdu 4419 线段树 扫描线 离散化 矩形面积
    hdu 4262(线段树)
    hfut 1287
    hdu 4747 (线段树)
  • 原文地址:https://www.cnblogs.com/zzyh/p/7157449.html
Copyright © 2020-2023  润新知