zoukankan      html  css  js  c++  java
  • POJ3336 Making the Grade

    思路:DP

    提交:1次

    题解:

    最开始我们可以想到,分两种序列都做一遍。
    先来证明一个结论:
    存在一种构造,使 (B) 中的数都在 (A) 中出现过,且这样不劣。
    (目的是为了转化暂时看起来虚无缥缈的DP)
    显然一个数成立,考虑 (B) 的前 (k-1) 项,向后插入一个数 (B_k)
    (B_{k-1}leq A_k) ,我们直接递增插入,否则 (B_k=B_{k-1}) ,亦或者存在一个 (j) ,使 (B_j,B_{j+1},cdots,B_{k}) 相等,且代价更小(中位数的性质)。
    这样我们考虑DP:
    (f[i][j])(i) 个数,最后一个数为 (j) (注意 (j) 是离散化后的位置)
    (f[i][j]=min_{0 leq k leq j}(f[i-1][k]+|j-A_i|))
    注意到对于一个 (i) 决策集合是在单调扩大的,所以可以用一个变量记录前面的最小值,直接转移。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
    	register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
    	do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*f;
    } const int N=2010;
    int n,m,a[N],b[N];
    int f[N][N],ans=1e+9;
    inline void main() {
    	n=g(); for(R i=1;i<=n;++i) b[i]=a[i]=g();
    	sort(b+1,b+n+1); R m=unique(b+1,b+n+1)-b-1; 
    	memset(f,0x3f,sizeof f); f[0][0]=0;
    	for(R i=1;i<=n;++i) {
    		R mn=f[i-1][0];
    		for(R j=1;j<=m;++j) {
    			mn=min(mn,f[i-1][j]);
    			f[i][j]=mn+abs(a[i]-b[j]);
    		}
    	} for(R i=1;i<=m;++i) ans=min(ans,f[n][i]);
    	printf("%d
    ",ans);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.09.18
    58

  • 相关阅读:
    Spring AOP中pointcut expression表达式解析
    java中Action层、Service层和Dao层的功能区分
    vim对erlang语法支持
    svn跳过某个目录
    时间,闰秒,及NTP
    grep
    【转】MySql数据库--mysql_real_escape_string()函数
    Linux sed 批量替换多个文件中的字符串
    求最大公约数
    怎么利用SQL语句查询数据库中具体某个字段的重复行
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11545585.html
Copyright © 2011-2022 走看看