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;
    }
    
  • 相关阅读:
    定时器的使用
    new LayoutParams 使用
    判断,日期是是昨天,前天 ,今天
    google推出的SwipeRefreshLayout下拉刷新用法
    Intent的Flag
    Eclipse Java注释模板设置详解
    Eclipse的模板设置代码
    Android如何在java代码中设置margin
    软键盘挡住输入框的解决方案
    Android自定义遮罩层设计
  • 原文地址:https://www.cnblogs.com/morslin/p/11855347.html
Copyright © 2011-2022 走看看