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\n", 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\n", dp[1][n][1]==INF ? 0:dp[1][n][1]);
    }
}

猜你喜欢

转载自www.cnblogs.com/ruthank/p/9575828.html