题目要求 求最大匹配,但是不能敬酒的人手交叉。要注意的是枚举的长度每次长度都是两倍增长。
状态方程:
dp[i][j] = dp[i+1][j-1] + (a[i]==b[j]) 如果区间两边可以间就那么就从中间往外推
dp[i][j] = max { dp[i][k] +dp[k+1][j] }
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<string> #include<vector> #include<queue> #include<map> #include<set> #include<stack> #define B(x) (1<<(x)) using namespace std; typedef long long ll; typedef unsigned long long ull; typedef unsigned ui; const int oo = 0x3f3f3f3f; //const ll OO = 0x3f3f3f3f3f3f3f3f; const double eps = 1e-9; #define lson rt<<1 #define rson rt<<1|1 void cmax(int& a, int b){ if (b > a)a = b; } void cmin(int& a, int b){ if (b < a)a = b; } void cmax(ll& a, ll b){ if (b > a)a = b; } void cmin(ll& a, ll b){ if (b < a)a = b; } void cmax(double& a, double b){ if (a - b < eps) a = b; } void cmin(double& a, double b){ if (b - a < eps) a = b; } void add(int& a, int b, int mod){ a = (a + b) % mod; } void add(ll& a, ll b, ll mod){ a = (a + b) % mod; } const ll MOD = 1000000007; const int maxn = 1100; int dp[maxn][maxn]; int a[maxn]; int main(){ int T, n, cas, v; scanf("%d", &T); for (int cas = 1; cas <= T; cas++){ scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); memset(dp, 0, sizeof dp); for (int L = 2; L <= n; L += 2) for (int i = 1; i + L - 1 <= n; i++){ int j = i + L - 1; dp[i][j] = dp[i + 1][j - 1] + (a[i] == a[j]); for (int k = i; k <= j; k++) dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]); } printf("%d\n", dp[1][n]); } return 0; }