P1880 [NOI1995]石子合并
参考的大佬的博客
求什么设什么,dp[l][r]为l到r堆范围的石子数量的最值
相邻合并为一堆,所以枚举最小值是2
这两堆又是由另外的两堆石子合并,可认为是由dp[l][k]和dp[k + 1][r]
根据k的值将对应范围分为了两部分,然后根据公式会分为更多部分
#include <bits/stdc++.h> using namespace std; int n,a[210]; int dp1[210][210],dp2[210][210]; int main(){ //freopen("in","r",stdin); ios::sync_with_stdio(0); cin >> n; for(int i = 1; i <= n; i++){ cin >> a[i]; a[i + n] = a[i]; } for(int i = 1; i <= 2 * n; i++) a[i] += a[i - 1]; //枚举区间长度,最小是2堆开始合并 for(int len = 2; len <= n; len++){ //枚举起点 for(int l = 1; l + len - 1 < 2 * n; l++){ int r = l + len - 1;//终点 dp1[l][r] = 99999; dp2[l][r] = -99999; //不能等于,等于的话就是一堆了 for(int k = l; k < r; k++){ dp1[l][r] = min(dp1[l][r],dp1[l][k] + dp1[k + 1][r] + a[r] - a[l - 1]); dp2[l][r] = max(dp2[l][r],dp2[l][k] + dp2[k + 1][r] + a[r] - a[l - 1]); } } } int minn = 99999; int maxx = -99999; for(int i = 1; i <= n; i++){ minn = min(minn,dp1[i][i + n - 1]); maxx = max(maxx,dp2[i][i + n - 1]); } cout << minn << endl << maxx; return 0; }