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;
    	}
    
  • 相关阅读:
    《自拍教程76》Python 一键批量安装第三方包
    Java 在 PDF 中添加表单域
    Spire.Cloud.Word 加密 Word 文档
    Java 添加超链接到 Word 文档
    为什么java8还在被大量使用?
    要替代C和Java 的后浪,现在混得怎么样?
    学习Java之前是否需要学习HTML
    半路出家学习Java是否能学出来
    学习Java语言有什么好处?
    Java只有中国开发者在用了吗?
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/14540133.html
Copyright © 2011-2022 走看看