给定数组, 将数组分为尽可能少的段使得每一个段的第一个或最后一个数字是段的长度, 求最少的段数
线性dp
令 dp[i] 表示将前 i 个数字全部分好段最少的段数
dp[0] = 0
枚举每一个 a[i], 这个数字有两种分段方案:
作为某个段的结尾: dp[i] = min(dp[i], dp[i - a[i]] + 1)
作为某个段的开头: dp[i + a[i] - 1] = min(d[i + a[i] - 1], dp[i - 1] + 1)
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned int;
using i128 = __int128;
#define TEST
#define TESTS int _; cin >> _; while(_--)
using namespace std;
void Main() {int n;vector<int> a(800000, 0);vector<int> dp(800000, 800000);cin >> n;for(int i = 1; i <= n; ++i) cin >> a[i];dp[0] = 0;for(int i = 1; i <= n; ++i) {// 作为结尾if(i - a[i] >= 0) dp[i] = min(dp[i - a[i]] + 1, dp[i]);// 作为开头dp[i + a[i] - 1] = min(dp[i + a[i] - 1], dp[i - 1] + 1);}if(dp[n] == 800000) cout << "-1\n";else cout << dp[n] << '\n';
}
int main() {ios :: sync_with_stdio(false);cin.tie(0); cout.tie(0);TESTS Main();return 0;
}