[HDU5693] [2016Astar] D Game [區間dp]
阿新 • • 發佈:2018-10-31
觀察到(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;
}