zoukankan      html  css  js  c++  java
  • USACO16OPEN 248

    题目传送门

    比较坑的区间(DP)


    定义f[i][j]为将i~j这段区间全都合并为一个数的最大值

    于是我很自然的就想到了这样转移:

    f[i][j] = max(f[i][j], max(f[i][k], f[k+1][j]));
    if(f[i][k] == f[k+1][j]) f[i][j] = max(f[i][j], f[i][k] + 1);
    

    但是,因为f[i][k]f[k+1][j]的最大值可能并不相邻,所以第一个转移是不对的,应该只有

    if(f[i][k] == f[k+1][j]) f[i][j] = max(f[i][j], f[i][k] + 1);
    

    这样就可以把这道题(A)掉了

    但是,这样其实还是不对的,能(A)是因为数据水,因为无法保证f[i][k]一定能被合成为它表示的数,所以还要标记一下它是否能合成为一个数

    if(f[i][k] == f[k + 1][j] && f[i][k] != -1) f[i][j] = max(f[i][j], f[i][k] + 1);
    

    所以最终代码是

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define LL long long
    LL read() {
        LL k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
            k = k * 10 + c - 48, c = getchar();
        return k * f;
    }
    char read_c() {
        char c = getchar();
        while(c != 'M' && c != 'C') c = getchar();
        return c;
    }
    int f[250][250], ans;
    int main() {
        int n = read(); memset(f, -1, sizeof(f));
        for(int i = 1; i <= n; ++i)
            f[i][i] = read(), ans = max(f[i][i], ans);
        for(int i = n-1; i >= 1; --i)
            for(int j = i+1; j <= n; ++j) {
                for(int k = i; k < j; ++k) {
                    if(f[i][k] == f[k+1][j] && f[i][k] != -1) f[i][j] = max(f[i][j], f[i][k] + 1);
                    ans = max(f[i][j], ans);
                }
            }
        cout << ans;
        return 0;
    }
    
  • 相关阅读:
    PowerDesigner如何设置字段为自增长
    Tab标签
    过滤数据集DataTable方法
    时间复杂度计算方法
    Oracle字符函数
    ASP.NET 应用程序生命周期概述
    在同一个DataSet中添加多个DataTable
    谈SQL SERVER数据库中的索引
    Abstract 与 Vitrual 用法
    活动图与流程图的区别
  • 原文地址:https://www.cnblogs.com/morslin/p/11855347.html
Copyright © 2011-2022 走看看