题意:有一排颜色不同的方块,消k个连续方块可得k*k分,问最多得多少分。
分析:
1、solve(l, r, k)---在方块l~r右边再拼上k个颜色等于A[r] 的方块所得到的新序列的最大得分。
2、决策:
(1)直接消去方块r,转移到solve(l, r - 1, 0) + (k + 1)2
(2)枚举i<r,使得a[i]=a[r],且a[i]!=a[i+1],转移到solve(i+1,r-1, 0)+solve(l,i,k+1).
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define lowbit(x) (x & (-x)) const double eps = 1e-8; inline int dcmp(double a, double b){ if(fabs(a - b) < eps) return 0; return a > b ? 1 : -1; } typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1e9 + 7; const double pi = acos(-1.0); const int MAXN = 200 + 10; const int MAXT = 10000 + 10; using namespace std; int dp[MAXN][MAXN][MAXN]; int color[MAXN]; int solve(int l, int r, int k){ if(l > r) return 0; int &ans = dp[l][r][k]; if(ans) return ans; ans = solve(l, r - 1, 0) + (k + 1) * (k + 1);//直接消去方块r for(int i = r - 1; i >= l; --i){ if(color[i] == color[r]){ ans = max(ans, solve(l, i, k + 1) + solve(i + 1, r - 1, 0)); } } return ans; } int main(){ int T; scanf("%d", &T); int kase = 0; while(T--){ int n; scanf("%d", &n); for(int i = 1; i <= n; ++i){ scanf("%d", &color[i]); } memset(dp, 0, sizeof dp); printf("Case %d: %d ", ++kase, solve(1, n, 0)); } return 0; }