dp+差分数组
前言:怎么也没想到要用dp来做,并且这个题目中如果列为1的话还要特殊考虑
题目地址
#include<bits/stdc++.h>
using namespace std;
//#define int long long
const int N = (int)5e3 + 10;
int dp[N][N][2]; // 0 表示上端点,1表示下端点
int t;
int n, m;
int a[N];
int chafen[N];
signed main() {
cin >> t;
while (t--) {
cin >> n >> m;
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++) {
dp[i][j][0] = dp[i][j][1] = 0;
a[i] = 0;
}
}
for (int i = 1; i <= m; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
dp[i][1][0] = dp[i][1][1] = 1; // 第一列中都可以当端点
}
for (int j = 2; j <= m - 1; j++) {
if (a[j] == 1) {
//vector<int> chafen(n + 2, 0);
for (int i = 0; i < n + 2; ++i)
chafen[i] = 0;
for (int k = 1; k <= n; k++) {
if (dp[k][j - 1][0]) chafen[k]++;
if (dp[k][j - 1][1]) chafen[k + 1]--;
}
int cnt = 0;
for (int k = 1; k <= n; k++) {
cnt += chafen[k];
if (cnt) {
dp[k][j][0] = dp[k][j][1] = 1;
}
}
continue;
}
for (int i = 1; i <= n; i++) {
if (dp[i][j - 1][0]) {
if (i - a[j] + 1 >= 1) {
dp[i][j][1] = 1;
dp[i - a[j] + 1][j][0] = 1;
}
}
if (dp[i][j - 1][1]) {
if (i + a[j] - 1 <= n) {
dp[i][j][0] = 1;
dp[i + a[j] - 1][j][1] = 1;
}
}
}
}
//for (int i = 1; i <= n; i++) {
// cout << dp[i][2][0] << " " << dp[i][2][1] << endl;
//}
//vector<int> chafen(n + 2, 0);
for (int i = 0; i < n + 2; ++i)
chafen[i] = 0;
for (int i = 1; i <= n; i++) {
if (dp[i][m - 1][0]) chafen[i]++;
if (dp[i][m - 1][1]) chafen[i + 1]--;
}int cnt = 0; int ans = 0;
for (int i = 1; i <= n; i++) {
cnt += chafen[i];
if (cnt) ans++;
}
cout << ans << endl;
}
return 0;
}