[HDU5693] [2016Astar] D Game [区间dp]

[ L i n k \frak{Link} ]


观察到(2,3)=1
在只能选择≥2个连续数字的情况下,无论一次删除几个数都可以拆分为删除两个或者三个数。
那么预处理删除两个和删除三个的情况,更大的区间合并。

样例良心啊(

我比较懒,就不log掉找公差了。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<ctime>
#include<cmath>
using namespace std;
int T, n, m, a[305], d[305], F[305][305];
int main() {
	scanf("%d", &T);
	while (T--) {
		memset(F, 0, sizeof(F));
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; ++i) {
			scanf("%d", &a[i]);
		}
		for (int i = 1; i <= m; ++i) {
			scanf("%d", &d[i]);
		}
		for (int i = 2; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				if (a[i] - a[i-1] == d[j]) {
					F[i-1][i] = 2;
					break;
				}
			}
		}
		for (int t, i = 3; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				F[i-2][i] = max(F[i-2][i-1], F[i-1][i]);
				if (a[i] - a[i-1] == d[j] && a[i-1] - a[i-2] == d[j]) {
					F[i-2][i] = 3;
					break;
				}
			}
		}
		for (int t, k = 4; k <= n; ++k) {
			for (int i = k; i <= n; ++i) {
				t = i-k+1;
				for (int j = 1; j <= m; ++j) {
					if (F[t][i-2]==k-2 && a[i]-a[i-1]==d[j]) {
						F[t][i] = k;
						break;
					}
					if (F[t+2][i]==k-2 && a[t+1]-a[t]==d[j]) {
						F[t][i] = k;
						break;
					}
					if (F[t][i-3]==k-3 && a[i]-a[i-1]==d[j] && a[i-1]-a[i-2]==d[j]) {
						F[t][i] = k;
						break;
					}
					if (F[t+3][i]==k-3 && a[t+1]-a[t]==d[j] && a[t+2]-a[t+1]==d[j]) {
						F[t][i] = k;
						break;
					}
					if (F[t+1][i-1]==k-2 && a[i]-a[t]==d[j]) {
						F[t][i] = k;
						break;
					}
					if (F[t+1][i-2]==k-3 && a[i]-a[i-1]==d[j] && a[i-1]-a[t]==d[j]) {
						F[t][i] = k;
						break;
					}
					if (F[t+2][i-1]==k-3 && a[i]-a[t+1]==d[j] && a[t+1]-a[t]==d[j]) {
						F[t][i] = k;
						break;
					}
				}
				if (F[t][i] != k) for (int j = t; j < i; ++j) F[t][i] = max(F[t][i], F[t][j] + F[j+1][i]);
			}
		}
		printf("%d\n", F[1][n]);
	}
	return 0;
}					break;
					}
					if (F[t+1][i-2]==k-3 && a[i]-a[i-1]==d[j] && a[i-1]-a[t]==d[j]) {
						F[t][i] = k;
						break;
					}
					if (F[t+2][i-1]==k-3 && a[i]-a[t+1]==d[j] && a[t+1]-a[t]==d[j]) {
						F[t][i] = k;
						break;
					}
				}
				if (F[t][i] != k) for (int j = t; j < i; ++j) F[t][i] = max(F[t][i], F[t][j] + F[j+1][i]);
			}
		}
		printf("%d\n", F[1][n]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Estia_/article/details/83513874