【POJ 1390】Blocks

http://poj.org/problem?id=1390
黑书上的例题,感觉我这辈子是想不到这样的dp了QAQ
\(f(i,j,k)\)表示将\(i\)\(j\)合并,并且假设未来会有\(k\)个与\(a_j\)同色的方块与\(j\)相连的最大得分。
如果直接消去第\(j\)个区域和未来会接到\(j\)后面的\(k\)块,那么
\(f(i,j,k)=f(i,j-1,0)+(b_j+k)^2\)
如果\(j\)与之前一起合并,假设与\(j\)颜色相同的是区域\(p\),那么
\(f(i,j,k)=f(i,p,k+b_j)+f(p+1,j-1,0),(i\leq p<j且a_p=a_j)\)
\(f(i,j,k)\)为两者的最大值。
答案即是\(f(1,n,0)\)
时间复杂度\(O(n^4)\)
\(n^4\)竟然能过!一直在想\(n^3\)QwQ(说得好像我\(n^4\)能想出来一样TwT)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 203;
int in() {
    int k = 0; char c = getchar();
    for (; c < '0' || c > '9'; c = getchar());
    for (; c >= '0' && c <= '9'; c = getchar())
        k = k * 10 + c - 48;
    return k;
}

int T, n, f[N][N][N], a[N], len[N], b[N], m;

int sqr(int x) {return x * x;}

int dp(int l, int r, int ex) {
    if (r < l) return 0;
    if (f[l][r][ex] != -1) return f[l][r][ex];
    int ans = dp(l, r - 1, 0) + sqr(len[r] + ex);
    for (int i = l; i < r; ++i)
        if (a[i] == a[r])
            ans = max(ans, dp(l, i, len[r] + ex) + dp(i + 1, r - 1, 0));
    return f[l][r][ex] = ans;
}

int main() {
    T = in();
    for (int i = 1; i <= T; ++i) {
        printf("Case %d: ", i);
        memset(f, -1, sizeof(f));
        memset(len, 0, sizeof(len));
        m = in();
        for (int j = 1; j <= m; ++j)
            b[j] = in();
        a[n = 1] = b[1]; len[1] = 1;
        for (int j = 2; j <= m; ++j)
            if (b[j] != b[j - 1]) {
                a[++n] = b[j];
                len[n] = 1;
            } else
                ++len[n];
        printf("%d\n", dp(1, n, 0));
    }
    return 0;
}

转载于:https://www.cnblogs.com/abclzr/p/5987058.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值