题目描述
给定一个1*n的地图,在里面玩2048,每次可以合并相邻两个(数值范围1-40),问最大能合出多少。注意合并后的数值并非加倍而是+1,例如2与2合并后的数值为3。
输入
第一行一个数n,接下来n行,每行一个数。
输出
一个数表示最大可以合出多少。
样例输入
4 1 1 1 2
样例输出
3
题解
明显的区间dp。设 dp[ i ][ j ] 为区间 [ i , j ] 可以合出的最大值,在 [ i , j ] 中枚举 k ,当 dp[ i ][ k ] == dp[ k+1 ][ j ] 时,更新 dp[ i ][ j ] = max( dp[ i ][ j ] , dp[ i ][ k ] + 1 ),但是注意,dp[ i ][ k ] 不能等于0。
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=248+10; const int inf=2e9+7; int dp[maxn][maxn],n,ans=0; template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n); for(int i=1;i<=n;i++){ read(dp[i][i]); ans=max(ans,dp[i][i]); } for(int len=2;len<=n;len++) for(int i=1;i+len-1<=n;i++){ int j=i+len-1; for(int k=i;k<j;k++) if(dp[i][k]==dp[k+1][j]&&dp[i][k]) dp[i][j]=max(dp[i][j],dp[i][k]+1); ans=max(ans,dp[i][j]); } cout<<ans<<endl; return 0; }