zoukankan      html  css  js  c++  java
  • HihoCoder

    有n堆石子,每次你可以把相邻的最少L堆,最多R堆合并成一堆。

    问把所有石子合并成一堆石子的最少花费是多少。

    如果不能合并,输出0。

    石子合并的变种问题。

    用dp[l][r][k]表示将 l 到 r 之间的石子合并成 k 堆。

    显然是k == 1 时,合并才是需要花费代价的。k >= 2时转移的时候不需要加代价。

    这个我当时非常不理解。然后后来想想确实是这样的。因为k >= 2的状态必然是由 k == 1的时候转移过来的。

    就是说将[l, r]分成k堆,必然要有几堆合并成一堆。

    同理,合并区间长度限制的时候也只在k == 1的时候考虑就好了。

    转移的时候分开按情况转移就好了。

    记忆化搜索的形式老是TLE。我也不知道为啥。。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int maxn = 100 + 10;
    const int INF = 0x3f3f3f3f;
    int n, L, R;
    int dp[maxn][maxn][maxn];
    int sum[maxn], a[maxn];
    
    //int DP(int l, int r, int k)
    //{
    //    if (k > r-l+1) return INF;
    //    if (k == r-l+1) return dp[l][r][k] = 0;
    //    if (dp[l][r][k] != INF) return dp[l][r][k];
    //
    //    if (k == 1)
    //    {
    //        for (int j = L; j <= R; j++)
    //            for (int i = l; i <= r-1; i++)
    //                dp[l][r][k] = min(dp[l][r][k], DP(l, i, j-1)+DP(i+1, r, 1)+sum[r]-sum[l-1]);
    //    }
    //    else
    //    for (int i = l; i <= r-1; i++)
    //        dp[l][r][k] = min(dp[l][r][k], DP(l, i, k-1)+DP(i+1, r, 1));
    //
    //    return dp[l][r][k];
    //}
    
    int main()
    {
        while(~scanf("%d%d%d", &n, &L, &R))
        {
            for (int i = 1; i <= n; i++) scanf("%d", &a[i]), sum[i] = sum[i-1]+a[i];
    
            memset(dp, INF, sizeof(dp));
    
            //printf("%d %d
    ", dp[1][1][1], 0x3f3f3f3f);
    
            for (int i = 1; i <= n; i++)
                for (int j = i; j <= n; j++)
                        dp[i][j][j-i+1] = 0;
    
            for (int len = 2; len <= n; len++)
            for (int l = 1; l+len-1 <= n; l++)
            {
                int r = l+len-1;
                for (int j = 2; j <= len; j++)
                    for (int k = l; k <= r-1; k++)
                        dp[l][r][j] = min(dp[l][r][j], dp[l][k][j-1]+dp[k+1][r][1]);
    
                for (int j = L; j <= R; j++)
                    for (int k = l; k <= r-1; k++)
                        dp[l][r][1] = min(dp[l][r][1], dp[l][k][j-1]+dp[k+1][r][1]+sum[r]-sum[l-1]);
            }
    
    
    
    //        int ans = DP(1, n, 1);
            printf("%d
    ", dp[1][n][1]==INF ? 0:dp[1][n][1]);
        }
    }
  • 相关阅读:
    智慧养老民政监管平台建设方案
    CF600E Lomsat gelral dsu on tree
    dsu on tree详解
    【Spring 从0开始】Spring5 新功能,整合日志框架 Log4j2
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 数据库事务参数
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 操作数据库
    【Spring 从0开始】AOP 操作
    【Spring 从0开始】AOP 操作中的相关术语、环境准备
  • 原文地址:https://www.cnblogs.com/ruthank/p/9575828.html
Copyright © 2011-2022 走看看