P1880 [NOI1995] 石子合併
阿新 • • 發佈:2021-08-30
這題沒什麼好說的吧。。記錄一下自己的一點想法
區間DP是從小區間得出最優解,大區間再合併小區間求最優解的。
對於這題,我們不妨設
如果我們通過列舉區間端點i,j來轉移,顯然是不行的。因為這樣不滿足小區間到大區間的要求,
會這樣算
所以我們要變通思路,小區間,那麼我們就列舉區間長度,在列舉區間左端點
就會這樣算
my code:
#include<bits/stdc++.h> #define rep(i,j,k) for(register int i(j);i<=k;++i) using namespace std; inline char gt() { static char buf[1 << 21], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; } template <typename T> inline void read(T &x) { register char ch = gt(); x = 0; int w(0); while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt(); while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt(); w ? x = ~(x - 1) : x; } template <typename T> inline void out(T x) { if(x < 0) x = -x, putchar('-'); char ch[20]; int num(0); while(x || !num) ch[++num] = x % 10 + '0', x /= 10; while(num) putchar(ch[num--]); putchar('\n'); } const int N = 207; int a[N]; int sum[N], n; int f[N][N], ff[N][N]; int main() { read(n); rep(i, 1, n) { read(a[i]); a[i + n] = a[i]; sum[i] = sum[i - 1] + a[i]; } rep(i, n + 1, 2 * n) sum[i] = sum[i - 1] + a[i]; memset(f, 0x3f, sizeof f); rep(i, 1, n * 2) f[i][i] = 0; rep(len, 2, n) for(register int l = 1, r = l + len - 1; l + len - 1 <= 2 * n; ++l, r++) { rep(k, l, r - 1) { f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r] + sum[r] - sum[l - 1]); ff[l][r] = max(ff[l][r], ff[l][k] + ff[k + 1][r] + sum[r] - sum[l - 1]); } } int ans1 = INT_MAX, ans2 = INT_MIN; rep(i, 1, n) { ans1 = min(ans1, f[i][i + n - 1]); ans2 = max(ans2, ff[i][i + n - 1]); } out(ans1); out(ans2); return 0; }
本文來自部落格園,作者:{2519},轉載請註明原文連結:https://www.cnblogs.com/QQ2519/p/15206078.html