USACO16OPEN 248
Posted wxl-ezio
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\)掉了
但是,这样其实还是不对的,因为无法保证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;
以上是关于USACO16OPEN 248的主要内容,如果未能解决你的问题,请参考以下文章
[luoguP3146] [USACO16OPEN]248(区间DP)