题目大意
题解
简单dp
假设一个数的移动方向确定了,那么这个数可以移到方向所指的任意一个位置,等价于把这个数拿掉最后再放
那么剩下的是一个上升子序列,设f[i][j]表示考虑完1~i,上一个的是j
如果a[i+1]<a[j],那么显然不能放,加上左移的代价
如果a[i+1]>a[j],那么可以放也可以不放,不放的话默认后面有更小的数(如果没有答案会更劣,不会影响),所以加上右移的代价
时间O(n^2)
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define inf 1152921504606846976ll
#define min(a,b) (a<b?a:b)
#define ll long long
//#define file
using namespace std;
ll f[5001][5001],ans,A,B;
int a[5001],n,i,j,k,l;
int main()
{
#ifdef file
freopen("agc032D.in","r",stdin);
#endif
scanf("%d%d%d",&n,&A,&B);
fo(i,1,n) scanf("%d",&a[i]);
memset(f,127,sizeof(f));
fo(i,1,n) f[i][i]=A*(i-1);
fo(i,1,n-1)
{
fo(j,1,i)
if (f[i][j]<inf)
{
if (a[i+1]<a[j]) f[i+1][j]=min(f[i+1][j],f[i][j]+B);
else f[i+1][i+1]=min(f[i+1][i+1],f[i][j]),f[i+1][j]=min(f[i+1][j],f[i][j]+A);
}
}
ans=9223372036854775807ll;
fo(i,1,n) ans=min(ans,f[n][i]);
printf("%lld
",ans);
fclose(stdin);
fclose(stdout);
return 0;
}