P3146 [USACO16OPEN]248 (区间DP)
题目描述
给定一个1*n的地图,在里面玩2048,每次可以合并相邻两个(数值范围1-40),问最大能合出多少。注意合并后的数值并非加倍而是+1,例如2与2合并后的数值为3.
这道题的思路:
状态:
f[i][j] 代表当前 i -> j的最大值 . 初始的f[i][i] = a[i].
然后枚举点 1 -> n-1 到 n 的区间.
然后中间再枚举断点 k.
方程就是 f[i][j] = max(f[k+1][j]+1,f[i][j]);
约束条件:
当且仅当两个区间所得到的最大值相同的时候才能往后更新.
代码:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int f[250][250],a[250]; int n,maxx,k,ans=-1; int main() { int i,tmp,j,t; scanf("%d",&n); for (i=1;i<=n;i++) { scanf("%d",&a[i]); f[i][i]=a[i]; } for (i=n-1;i>=1;i--) for (j=i+1;j<=n;j++) for (k=i;k<=j-1;k++) { if (f[i][k]==f[k+1][j]) f[i][j]=max(f[k+1][j]+1,f[i][j]); ans=max(ans,f[i][j]); } printf("%d",ans); }