• HDU 4283 You Are the One


    题意:给定n(n<=100)个人,每个人有个固定的屌丝值D。 起初这些人是站成一行,当第i个人第j个去面试的时候他的值是 Di*j。
    要求所有人面试之后 这些值加起来是最小的。
    队伍站成一行(其实就是个队列), 队列头部里的人可以到一个小黑屋子里,先进黑屋子的必须后出来(相当于一个栈)。
    然后队首的人可以选择进黑屋或者去面试,黑屋里的也可以选择去面试。 要求最少的Di*j 值之和。
    ===============================================================================
    题目分析:
    这个题目也是想了好久, 最初看的时候一直认为DP式子是:
     dp[L][R] = min( dp[L][R], dp[L+1][k] + a[L]*k + dp[k+1][R] )   (L<= k <= R)
    起初是这样认为的。但是后来发现这样的子结构其实是不对的, 我们对其位置交换的时候会出现一些问题。
    后来看看题解发现问题所在:
    子结构其实应该是 DP[L][R] 代表区间L,R之间 (0,R-L)次选择的方式。并不应该是(L,R)的选择方式。
    (sum[i] 代表从a[0]加到a[i])
    故得到一个递推式: dp[L][R] = min(dp[L][R], dp[L+1][L+k] + a[L]*k + dp[L+k+1][R] + (sum[R]-sum[L+k])*(k+1) );
    关键是:为什么要加上他 (sum[R]-sum[L+k])*(k+1) 。 前面我们  dp[L+1][L+k] 这个区间不用加是因为我们最先选的就是这个区间,所以不加。
    至于区间dp[L+k+1][R],  因为我们的算的是区间(L+k+1,R)的第k次选择的结果,而k是(0,R-L-k-1)的。因此我们少加上了 (sum[R]-sum[L+k])*(k+1) 。
    =========================================================================================
     
     
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL INF = 0xfffffff;
    const LL maxn = 105;
    int dp[maxn][maxn], a[maxn], sum[maxn];
    
    int DFS(int L,int R)
    {
        if(dp[L][R])
            return dp[L][R];
        if(L > R)
            return 0;
    
        dp[L][R] = INF;
        for(int k=0; k<=R-L; k++)///在区间【L,R】内,这个数该如何去选择
        {///假设第L个数字,要在第K次选择
            dp[L][R] = min(dp[L][R], DFS(L+1, L+k) + a[L]*k + DFS(L+k+1,R) + (sum[R]-sum[L+k])*(k+1) );
        }
       // printf("dp[%d][%d]:%d
    ",L, R, dp[L][R]);
        return dp[L][R];
    }
    /*
    第L个元素第k个出场拍,
    */
    int main()
    {
        int T, n, cas = 1;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &n);
            memset(dp, 0, sizeof(dp));
            for(int i=0; i<n; i++)
                scanf("%d", &a[i]);
            sum[0] = a[0];
    
            for(int i=1; i<n; i++)
                sum[i] = sum[i-1] + a[i];
    
            printf("Case #%d: %d
    ",cas ++, DFS(0, n-1));
        }
        return 0;
    }
    
    /*
    2
    2
    4 5
    
    
    2
    5
    1 2 3 4 5
    
    5
    5 4 3 2 2
    */
  • 相关阅读:
    ngx_lua_waf
    一致性hash算法
    BloomFilter理解
    SkipList理解
    es中的一些知识点记录
    普通类、抽象类和接口区别:
    spring中的事件 applicationevent 讲的确实不错(转)
    CMS和G1的区别,以及Parallel
    SpringBoot优化内嵌的Tomcat ---设置MaxConnections
    tomcat启动nio,apr详解以及配置
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4838427.html
Copyright © 2020-2023  润新知