题目链接
LOJ:https://loj.ac/problem/2292
洛谷:https://www.luogu.org/problemnew/show/P5336
Solution
区间(
m dp),状态比较难想...为啥网上好多仙人说这题很蠢,可能是我太菜了吧
设(f[l][r])表示([l,r])消完的最小代价,(g[l][r][x][y])表示把([l,r])的值域消成([x,y])的最小代价。
注意这题只需要大小关系,所以可以离散化。
转移就很好办了,先转移(g),枚举(r)号元素删不删,然后在由(g)转移(f),具体看下代码注释吧。
复杂度(O(n^5))。
Code
#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('
');}
#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;
}