题目描述
给定一个1*n的地图,在里面玩2048,每次可以合并相邻两个(数值范围1-40),问最大能合出多少。注意合并后的数值并非加倍而是+1,例如2与2合并后的数值为3。
输入格式
一个正整数n(2<=n<=248),以及n个正整数 a i {a_i} ai(1<= a i {a_i} ai<=40).
输出格式
求合并后的最大数字.
思路
用
f
[
i
]
[
j
]
{f[i][j]}
f[i][j]来表示区间i~j可合出的最大数字,只需再用一个DP方程转移即可:(很显然是时间复杂度O(
n
3
{n^3}
n3)的 优秀 算法)
(如果可以合并
f
[
i
]
[
k
]
{f[i][k]}
f[i][k]和分
f
[
k
+
1
]
[
j
]
{f[k+1][j]}
f[k+1][j]即
a
[
k
]
{a[k]}
a[k]=
a
[
k
+
1
]
{a[k+1]}
a[k+1])
f
[
i
]
[
j
]
{f[i][j]}
f[i][j]=max(
f
[
i
]
[
j
]
{f[i][j]}
f[i][j],
f
[
i
]
[
k
]
+
1
{f[i][k]+1}
f[i][k]+1).
代码
#include<bits/stdc++.h>
#define N 258
using namespace std;
int n,ans=0;
int a[N],f[N][N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
f[i][i]=a[i];//初始化f数组.
for(int t=1;t<=n-1;t++)//的用这个间接确定j不然可能会WA
for(int i=n;i>=1;i--)
{
int j=i+t;
if(j>n)continue;//越界则返回.
for(int k=i;k<j;k++)
{
if(f[i][k] == f[k+1][j] && f[i][k] != 0 && f[k+1][j] != 0)
{
f[i][j] = max(f[i][j], f[i][k] + 1);
ans = max(ans, f[i][j]);//记录最大值(不一定是f[1][n]!)
}
}
}
cout<<ans<<endl;
return 0;
}