zoukankan      html  css  js  c++  java
  • UVA12170 轻松爬山 Easy Climb

    UVA12170 轻松爬山 Easy Climb

    给定一个序列和一个数 d ,需要改变序列中的元素, 使得相邻元素的差值小于等于 d
    求改变的最小值


    エラー発生:没初始化no指针。。


    Solution

    我们定义 (dp[i][j]) 为 处理完第 i 座山, 且第 (i) 座山处理后的高度为 (j) 的最小花费
    首先出现一个问题:j的状态总数过大
    发现处理后的状态总是以 nd 成倍的增长
    于是离散化一下

    然后如果每次都枚举每个高度的话,复杂度将达到 (O(n^{4})) 无法接受
    我们拿单调队列优化一下,可以省掉一轮枚举, 复杂度降至 (O(n^{3}))
    题解的单调队列用法很妙
    注意到上一轮的答案其实是个先减再增的
    于是我们只用拿一个指针维护头即可

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    #define LL long long
    #define REP(i, x, y) for(LL i = (x);i <= (y);i++)
    using namespace std;
    LL RD(){
        LL out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const LL maxn = 110, inf = 1e18;
    LL na, num, d;
    LL h[maxn];
    LL ori[1000010], no;
    LL dp[maxn][1000010];
    int init(){
    	no = 0;
    	num = RD(), d = RD();
    	REP(i, 1, num){
    		h[i] = RD();//读入并把可能的高度离散化
    		REP(j, -num, num){
    			ori[++no] = h[i] + j * d;
    			}
    		}
    	if(abs(h[num] - h[1]) > (num - 1) * d){//判断合法
    		puts("impossible");
    		return 0;
    		}
    	sort(ori + 1, ori + 1 + no);
    	no = unique(ori + 1, ori + 1 + no) - ori - 1;
    	REP(i, 1, num){
    		REP(j, 1, no){
    			dp[i][j] = inf;
    			}
    		}
    	REP(i, 1, no){
    		if(ori[i] == h[1])dp[1][i] = 0;//边界
    		}
    	return 1;
    	}
    void work(){
    	REP(i, 2, num){
    		LL k = 1;
    		REP(j, 1, no){
    			while(k <= no && ori[k]  + d < ori[j])k++;//确认下界
    				while(k + 1 <= no && ori[k + 1] <= ori[j] + d && dp[i - 1][k + 1] <= dp[i - 1][k])
    					k++;//确认上界条件下 找到队头
    			dp[i][j] = min(dp[i][j], dp[i - 1][k] + abs(ori[j] - h[i]));
    			}
    		}
    	REP(i, 1, no){
    		if(ori[i] == h[num])
    			cout<<dp[num][i]<<endl;
    		}
    	}
    int main(){
    	na = RD();
    	while(na--){
    		if(!init())continue;
    		work();
    		}
    	return 0;
    	}
    
  • 相关阅读:
    Compile、Make和Build的区别
    IntelliJ IDEA 学习(三):IntelliJ IDEA 快捷键、配置优化
    【HTML5 】手机重力与方向感应的应用——摇一摇效果
    IntelliJ IDEA 学习(二):Intellij IDEA 创建Web项目并在Tomcat中部署运行IDEA
    html学习一(html简史及doctype)
    IntelliJ IDEA 学习(一):IntelliJ IDEA 破解方法(已验证)
    连接oracle时报错:ORA-28001: the password has expired
    IDEA使用(1)intellIJ idea 配置 svn
    node.js的npm详解
    【朴灵评注】JavaScript 运行机制详解:再谈Event Loop
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/14540133.html
Copyright © 2011-2022 走看看