zoukankan      html  css  js  c++  java
  • AGC032D Rotation Sort

    AGC032D

    有个排列(p_i),每次可以以(A)的代价将某个数移到右边的一个位置,或者可以以(B)的代价移到左边的一个位置。

    问将其变成升序排列花的最小代价。

    (nle 5*10^3)


    考虑(p_x=1)的位置:最终它一定要移到最左边。移到最左边有两种方法:花(B)的代价将(p_x)移到最左边;花(A*左边的数的个数)的代价将左边的数移到(p_x)的右边。注意到如果我们用了后面的这个操作,我们完全可以让(p_x)左边的数任意插入到(x)右边的任意位置,于是可以先将(x)右边的数排列好,直接按照顺序插进去一定是最优的。

    第一种操作相当于把序列中的(1)剔除掉,接着做剩下的子问题;第二种操作形成的子问题为原来的一段后缀。

    于是可以DP:(f_{i,j})表示考虑区间([i,n]),剔除掉了小于等于(j)的数,这个问题的最小代价。

    转移的时候需要一个辅助数组(c_{i,j})表示([j,i])中大于(p_j)的数的个数。

    总时间复杂度(O(n^2))


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <climits>
    #define N 5010
    #define ll long long
    int n;
    ll A,B;
    int p[N],re[N];
    ll f[N][N];
    int c[N][N];
    void upd(ll &a,ll b){a=min(a,b);}
    int main(){
    //	freopen("in.txt","r",stdin);
    	scanf("%d%lld%lld",&n,&A,&B);
    	for (int i=1;i<=n;++i)
    		scanf("%d",&p[i]),re[p[i]]=i;
    	for (int j=1;j<=n;++j)
    		for (int i=re[j]-1;i>=1;--i)
    			c[j][i]=c[j][i+1]+(p[i]>j);
    	memset(f,127,sizeof f);
    	for (int j=0;j<=n;++j)
    		f[n+1][j]=0;
    	for (int i=n;i>=1;--i){
    		f[i][n]=0;
    		for (int j=n-1;j>=0;--j){
    			if (c[j+1][i]==0)
    				f[i][j]=f[i][j+1];
    			else
    				f[i][j]=min(f[i][j+1]+B,f[re[j+1]+1][j+1]+A*c[j+1][i]);
    		}
    	}
    	printf("%lld
    ",f[1][0]);
    	return 0;
    }
    
  • 相关阅读:
    Javascript 函数表达式
    当你在浏览器地址栏输入一个URL后回车,将会发生的事情?
    Angularjs 脏值检测
    Angularjs 双向绑定机制解析
    AngularJS 初用总结
    从jquery里的$.ajax()到angularjs的$http
    XSS攻击及防御
    很赞的源码平台
    GET和POST
    [转]xxx.hbm.xml模版
  • 原文地址:https://www.cnblogs.com/jz-597/p/13747211.html
Copyright © 2011-2022 走看看