1 条题解

  • 0
    @ 2025-8-24 22:31:54

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar logfk
    不是哥们,退役了还看啊

    搬运于2025-08-24 22:31:54,当前版本为作者最后更新于2021-07-20 16:28:58,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题意

    题意可直接转化为:

    每天共有 1212 个小时,每走一条路会消耗一定小时,用尽后或大于剩余时间当天将不能再走。

    以及,奇数天走路的正方向,偶数天走路的反方向,求从起点到终点所用最短时间(优先天数,天数相同比较当天剩余时间)时的路径。

    样例为:

    第一天:1541\to5\to4

    第二天:留在 44

    第三天:434\to3

    分析

    如果想要保证走的时间最短,就应该使用最短路,我们从一个点出发到一个点时,以天数为第一关键字,当前天数所剩时间为第二关键字进行优先队列的标准进行 Dij,如果当前天的时间加上走这条的时间小于等于 1212 则可以转移,如果大于则无法转移。

    但是这并不能覆盖样例的等候情况,因此我们需要判断是否能够在一个地点等一天,所以我们直接在判断之后进行一次下一天的过渡,在转移过程中记录相关信息,最后到终点时直接输出即可。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    int read()
    {
    	int x=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-') f=-f;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=x*10+ch-'0';
    		ch=getchar();
    	}
    	return x*f;
    }
    struct node{
    	int da,ti,np;
    	friend bool operator < (node x,node y)
    	{
    		if(x.da==y.da) return x.ti>y.ti;
    		return x.da>y.da;
    	}
    };//天数,天数相同比较时间
    priority_queue<node> q;
    int hpla[110],st,to[2010],nxt[2010],head[2010],val[2010],fl[2010],cnt,vis[110][2][20],pre[110],hpt[110],hpti[110];
    int ansp[110],ansx[110],anst[110],ansti[110];
    void addedge(int x,int y,int z,int ff)
    {
    	to[++cnt]=y;
    	nxt[cnt]=head[x];
    	head[x]=cnt;
    	val[cnt]=z;
    	fl[cnt]=ff;//正图还是反图
    }
    void out(int x,int &nc)
    {
    //	cout<<x<<nc<<endl;
    //	if(x==0) return;
    	ansp[nc]=pre[x];
    	ansx[nc]=x;
    	anst[nc]=hpt[x];
    	ansti[nc]=hpti[x];//取出路径
    	nc++;
    	if(pre[x]==st) return;
    	out(pre[x],nc);
    }
    int main()
    {
    	int x,y,z;st=read();
    	int ed=read(),n=read(),m=read();
    	memset(hpt,0x3f,sizeof(hpt));
    	memset(hpti,0x3f,sizeof(hpti));
    	for(int i=1;i<=m;i++)
    	{
    		x=read(),y=read(),z=read();
    		addedge(x,y,z,1);
    		addedge(y,x,z,0);
    	}
    	vis[st][1][0]=1;
    	q.push((node){1,0,st});
    	while(!q.empty())
    	{
    		node nq=q.top();
    		q.pop();
    //		cout<<nq.np<<" "<<nq.da<<" "<<nq.ti<<endl;
    		if(nq.np==ed)//到了直接输出
    		{
    			int cc=0;
    			out(nq.np,cc);
    			for(int i=cc-1;i>=0;i--)
    			{
    				cout<<ansp[i]<<" "<<ansx[i]<<" "<<anst[i]<<" "<<ansti[i]<<endl;
    			}
    			return 0;
    		}
    		x=nq.np;
    		int d=nq.da,tt=nq.ti;
    		for(int i=head[x];i;i=nxt[i])
    		{
    			int ft=to[i],ro=val[i];
    			if(tt+ro<=12)//如果一天还未结束
    			{
    //				cout<<ft<<" "<<ro<<endl;
    				if(!vis[ft][d%2][tt+ro]&&d%2==fl[i])//当前时间没有走过
    				{
    					if(d<hpt[ft]||(d==hpt[ft]&&tt+ro<hpla[ft]))//剩余时间更优
    					{
    						pre[ft]=x;
    						hpt[ft]=d;
    						hpti[ft]=ro;
    						hpla[ft]=ro+tt;
    					}
    					vis[ft][d%2][tt+ro]=1;
    					q.push((node){d,tt+ro,ft});
    				}
    			}
    		}
    		if(!vis[x][(d+1)%2][0])//注意!可以选择在某个地方停留一天
    		{
    			q.push((node){d+1,0,x});
    		}
    	}
    }
    
    • 1

    信息

    ID
    6837
    时间
    1000ms
    内存
    500MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者