agc032D - Rotation Sort

题目大意


题解

简单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\n",ans);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2020-09-27 22:28  gmh77  阅读(104)  评论(0编辑  收藏  举报