zoukankan      html  css  js  c++  java
  • UVA12170 Easy Climb

    题面传送


    题意:给了(n)个堆的高度,要求改变堆的高度,首尾不可改变,使得队列的任意相邻的两数之差(leqslant d),求最小代价。


    (dp[i][j])表示将第(i)个堆的高度改为(j)时,(1 sim i)的最小代价。
    转移很好写:(dp[i][j] = min{dp[i - 1][k] } + |a[i] - j| (j - d leqslant k leqslant j + d)).
    但是这样时空双爆。


    用优先队列可以满足时间复杂度,但是空间复杂度怎么办呢?
    这个就很妙了:(h[i])虽然很大,但是(n)只有(100),所以肯定有很多状态用不上。
    准确来说,只有(a[i] + k * d(kin [0,n]))个数会用到。
    根据一种“最优”的思想,在最小代价的前提下满足条件,一定是把原来差大于(d)的情况改成刚好等于(d)的情况,再改小了就是多余。
    有了这个结论,dp数组的第二维最多只有(n^2)个了。这样我们离散化后,所有问题就解决了。


    我也不知道为啥,这题不难,但是因为各种错误调了好长时间。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<queue>
    #include<assert.h>
    #include<ctime>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
    typedef long long ll;
    typedef double db;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 102;
    const int maxs = 5e4 + 2;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    int n, d;
    
    int cnt = 0, _n;
    ll a[maxn], b[maxs];
    In void init()
    {
    	cnt = 0;
    	for(int i = 1; i <= n; ++i) 
    		for(int j = -n; j <= n; ++j) 
    			if(a[i] + d * j >= 0) b[++cnt] = a[i] + d * j;
    	sort(b + 1, b + cnt + 1);
    	_n = unique(b + 1, b + cnt + 1) - b - 1;
    }
    ll dp[maxn][maxs];
    struct Node{ll v; int p;};
    deque<Node> q;
    In ll DP()
    {
    	Mem(dp, 0x3f);
    	dp[1][lower_bound(b + 1, b + _n + 1, a[1]) - b] = 0;
    	for(int i = 2; i < n; ++i)
    	{
    		q.clear();
    		for(int j = 1, x = 1; j <= _n; ++j)
    		{
    			while(x <= _n && b[x] <= b[j] + d)
    			{
    				while(!q.empty() && q.back().v >= dp[i - 1][x]) q.pop_back();
    				q.push_back((Node){dp[i - 1][x], x});
    				++x;
    			}
    			while(!q.empty() && b[q.front().p] < b[j] - d) q.pop_front();
    			if(!q.empty()) dp[i][j] = q.front().v + abs(a[i] - b[j]);
    		}
    	}
    	ll ret = INF;
    	for(int i = 1; i <= _n; ++i) 
    		if(abs(b[i] - a[n]) <= d) ret = min(ret, dp[n - 1][i]);
    	return ret;
    }
    
    int main()
    {
    	int T = read();
    	while(T--)
    	{
    		n = read(), d = read();
    		for(int i = 1; i <= n; ++i) a[i] = read();
    		init();
    		ll ans = DP();
    		if(ans == INF) puts("impossible");
    		else write(ans), enter;
    	}
    	return 0;
    }
    
  • 相关阅读:
    flannel网络的VXLAN及host-gw
    K8S中Harbor使用Nginx反向代理无法获取image
    kubernetes cluster IP not with in the service CIDR
    supervisor重启服务失败
    Centos系统磁盘目录分析工具-Ncdu
    计算机网络中这些高频考题,你还在死记硬背吗?(三)
    计算机网络中这些高频考题,你还在死记硬背吗?(二)
    计算机网络中这些高频考题,你还在死记硬背吗?(一)
    基于web的图书管理系统设计与实现
    一条贪吃蛇的使命——零基础入门贪吃蛇游戏(附演示地址)
  • 原文地址:https://www.cnblogs.com/mrclr/p/14514011.html
Copyright © 2011-2022 走看看