HihoCoder - 1636 Pangu and Stones(区间DP)

Posted ruthank

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HihoCoder - 1636 Pangu and Stones(区间DP)相关的知识,希望对你有一定的参考价值。

有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]);
    }
}

 

以上是关于HihoCoder - 1636 Pangu and Stones(区间DP)的主要内容,如果未能解决你的问题,请参考以下文章

hihocoder1636 Pangu and Stones

Pangu and Stones HihoCoder - 1636 区间DP

HihoCoder - 1636 Pangu and Stones(区间DP)

Hihocoder1636Pangu and Stones(区间DP)

Pangu and Stones(HihoCoder-1636)(17北京OL)区间DP

2017ICPC北京 J:Pangu and Stones