1. 程式人生 > >[HDU5693] [2016Astar] D Game [區間dp]

[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; }