zoukankan      html  css  js  c++  java
  • loj 2759「JOI 2014 Final」飞天鼠

    loj

    这题有在一棵树上上升或者下降的操作,稍加分析后可以发现上升操作如果不是一定要做(指高度不足以到下一棵树或者是最后到达(n))就不做,下降操作也是如果不是一定要做(指到达下一棵树时高度过高)就不做,因为如果提前做了,可能会导致后面要浪费一些步数使得移动合法.然后这个移动过程就会分成两段,先是一直移动或者下降,不用上升,然后会每次上升再移动,一直到终点

    先看前一段的移动,如果移动的时候正好能移到下一棵树就直接移,如果移的时候高度过高就往下移一点直到能正好移动到下一棵树上.这里对每个点记(di_x)表示从起点到这里用了多久.注意我们还需要知道在某个树上所在的高度,由于这一部分没有上升操作,并且每过一个单位时间会下降1,所以在某点高度为(X-di_x).然后这个(di_x)应当记的是最短用时,因为用时越短,在的位置也越高,然后对后续转移也越有利,至于有可能要强制往下移,那只要在该移的时候向下移动就行,用时短一定不必用时长劣

    还有一种情况,是移到下一棵树会移到(<0)的高度,这时候我们就要往上移,移到能飞到下一棵树的位置,然后往下一棵树移.移到下一棵树后高度会变为0,这时候对于任何移动,我们都是先往上移(t_i(t_ile H_x)),然后飞到下一棵树,所以用时都是(2t_i).那么上面两种情况就可以分别用(dij)来转移了.注意如果在第一种移动过程中移到了(n),那么就可以更新答案了,所以最终答案为(min()这种情况的贡献(,dis_n+H_n))

    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db long double
    
    using namespace std;
    const int N=1e5+10;
    int rd()
    {
    	int x=0,w=1;char ch=0;
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*w;
    };
    int n,m,X,h[N],e[N*3][3];
    struct node
    {
    	LL x,d;
    	bool operator < (const node &bb) const {return d>bb.d;}
    };
    priority_queue<node> q,qq;
    int to[N<<4],nt[N<<4],w[N<<4],hd[N],tot=1;
    void add(int x,int y,int z)
    {
    	++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;
    }
    LL di[N],ans=1ll<<50;
    
    int main()
    {
    	n=rd(),m=rd(),X=rd();
    	for(int i=1;i<=n;++i) h[i]=rd();
    	for(int i=1;i<=m;++i)
    		for(int j=0;j<=2;++j)
    			e[i][j]=rd();
    	for(int i=1;i<=m;++i)
    	{
    		int x=e[i][0],y=e[i][1],z=e[i][2];
    		add(x,y,z),add(y,x,z);
    	}
    	memset(di,0x3f3f3f,sizeof(LL)*(n+1));
    	qq.push((node){1,di[1]=0});
    	LL he=X;
    	while(!qq.empty())
    	{
    		int x=qq.top().x;
    		LL d=qq.top().d;
    		qq.pop();
    		if(d>di[x]) continue;
    		if(x==n) ans=min(ans,di[x]+h[n]-(he-di[x]));
    		for(int i=hd[x];i;i=nt[i])
    		{
    			int y=to[i];
    			if(he-di[x]-w[i]<=0&&w[i]<=h[x]) q.push((node){y,di[x]+w[i]-(he-di[x]-w[i])});
    			else
    			{
    				LL dt=max(0ll,he-di[x]-w[i]-h[y]);
    				if(di[y]>di[x]+w[i]+dt&&di[x]+w[i]+dt<=he) qq.push((node){y,di[y]=di[x]+w[i]+dt});
    			}
    		}
    	}
    	memset(hd,0,sizeof(int)*(n+1)),tot=1;
    	for(int i=1;i<=m;++i)
    	{
    		int x=e[i][0],y=e[i][1],z=e[i][2];
    		if(h[x]>=z) add(x,y,z<<1);
    		if(h[y]>=z) add(y,x,z<<1);
    	}
    	memset(di,0x3f3f3f,sizeof(LL)*(n+1));
    	while(!q.empty())
    	{
    		int x=q.top().x;
    		LL d=q.top().d;
    		q.pop();
    		if(d>di[x]) continue;
    		if(d<di[x]) di[x]=d;
    		for(int i=hd[x];i;i=nt[i])
    		{
    			int y=to[i];
    			if(di[y]>di[x]+w[i])
    				q.push((node){y,di[y]=di[x]+w[i]});
    		}
    	}
    	ans=min(ans,di[n]+h[n]);
    	printf("%lld
    ",ans<(1ll<<50)?ans:-1);
    	return 0; 
    }
    
  • 相关阅读:
    代码注入——c++代码注入
    Windows 用来定位 DLL 的搜索路径
    LoadLibraryA与GetProcAddress介绍
    DLL 函数导出的规则和方法
    C++ dll的隐式与显式调用
    C++ main函数的参数
    DLL注入之修改PE静态注入
    用户权限设置和进程权限提升
    DLL注入之windows消息钩取
    c++回调函数
  • 原文地址:https://www.cnblogs.com/smyjr/p/11618543.html
Copyright © 2011-2022 走看看