LOJ:https://loj.ac/problem/2292c++
洛谷:https://www.luogu.org/problemnew/show/P5336git
區間\(\rm dp\),狀態比較難想...爲啥網上好多仙人說這題很蠢,多是我太菜了吧spa
設\(f[l][r]\)表示\([l,r]\)消完的最小代價,\(g[l][r][x][y]\)表示把\([l,r]\)的值域消成\([x,y]\)的最小代價。code
注意這題只須要大小關係,因此能夠離散化。get
轉移就很好辦了,先轉移\(g\),枚舉\(r\)號元素刪不刪,而後在由\(g\)轉移\(f\),具體看下代碼註釋吧。it
複雜度\(O(n^5)\)。io
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } void print(int x) { if(x<0) putchar('-'),x=-x; if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define ll long long #define pii pair<int,int > #define vec vector<int > #define pb push_back #define mp make_pair #define fr first #define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 55; const int inf = 1e9; const lf eps = 1e-8; const int mod = 1e9+7; int f[55][55],g[55][55][55][55],v[maxn],t[maxn],n,a,b,m; void init() { read(n),read(a),read(b); FOR(i,1,n) read(v[i]),t[i]=v[i]; sort(t+1,t+n+1);m=unique(t+1,t+n+1)-t-1; FOR(i,1,n) v[i]=lower_bound(t+1,t+m+1,v[i])-t; } void chmin(int &x,int y) {if(x>y) x=y;} void chmax(int &x,int y) {if(x<y) x=y;} #define sqr(x) ((x)*(x)) int main() { init(); memset(f,63,sizeof f); memset(g,63,sizeof g); FOR(i,1,n) { f[i][i]=a; FOR(l,1,m) FOR(r,l,m) if(l<=v[i]&&v[i]<=r) g[i][i][l][r]=0; else g[i][i][l][r]=a; //初值注意下 } for(int len=2;len<=n;len++) for(int l=1;l<=n-len+1;l++) { int r=l+len-1; for(int x=1;x<=m;x++) for(int y=x;y<=m;y++) { if(x<=v[r]&&v[r]<=y) chmin(g[l][r][x][y],g[l][r-1][x][y]); // 不刪r for(int k=l+1;k<=r;k++) chmin(g[l][r][x][y],g[l][k-1][x][y]+f[k][r]); // 刪r,枚舉包括r的區間 chmin(f[l][r],g[l][r][x][y]+a+b*sqr(t[y]-t[x])); //轉移f } } write(f[1][n]); return 0; }