题目链接:https://codeforces.com/contest/1312
题目大意:
想法:
考虑区间DP
我们定义 f(i,j) 代表区间 i 到 j 的最小长度,w(i,j) 代表 区间 i 到 j的数字
转移方程也很容易想到
当 f(i,k) = f(k+1,j) = 1 && w(i,k) = w(k+1,j) f(i,j) = 1 ,w(i,j) = w(i,k) + 1
#pragma GCC optimize(3,"Ofast","inline")//O3优化 #pragma GCC optimize(2)//O2优化 #include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #include <cstring> #define LL long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) const double eps = 1e-10; const int maxn = 500 + 10; const LL mod = 998244353; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; int f[maxn][maxn]; int w[maxn][maxn]; int main() { ios::sync_with_stdio(0); memset(f,INF, sizeof(f)); int n; cin >> n; for (int i = 1;i <= n;i++) { f[i][i] = 1; cin >> w[i][i]; } for (int l = 2;l <= n;l++) { for (int i = 1;l+i-1 <= n;i++) { int j = l + i - 1; for (int k = i;k <= j;k++) { f[i][j] = min(f[i][j],f[i][k]+f[k+1][j]); if (w[i][k] == w[k+1][j] && f[i][k] == f[k+1][j] && f[i][k] == 1) { f[i][j] = 1; w[i][j] = w[i][k] + 1; } } } } cout << f[1][n] << endl; return 0; }