L3 天梯地图

L3 天梯地图

天梯地图题目
当我看到这道题的第一思路是,这道题肯定是用搜索,至于是深搜还是广搜,我选择了深搜。其实对于搜索这类题目,我是比较害怕的,因为最近写搜索的题目写的有点少了,但是,迎难而上的道理我还是懂的,于是我就开始动手敲代码,~~~~~~~~~一段时间以后,我终于写完了这道题的深搜代码,于是我满怀信心的提交了上去,但是,出问题了,一部分样例超时,没关系,肯定是深搜时间复杂度太高了,我换个思路吗,改为广搜一定可以 ~~~~~~~~~有过了一段时间,广搜的代码也被我写好了,这下一定可以了吧,于是我再次满怀信心的提交了广搜的代码,什么,还是超时,这个结果让我很绝望。这下我终于意识到思路错了,哎,最终我还是被困难给打败了,我手动百度了一下,然后crtl c,ctrl v,呀过了,太神奇了吧。作者一道题过程真的是太辛苦了,不由得感慨一下。

进入正题,这道题使用两次dijkstra即可,但是需要稍微改变一下,例如求最快最短的情况下,慢的需要更新为快的毋庸置疑,同时同样快的应该考虑路径长度是否需要更新;下面是这道题的代码

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int maxn=5000;
int head[maxn],tot=0;
int s,e,n,m;
const int inf=0x3f3f3f3f;
struct Edge{
	int v;
	int len,time,next;
	
}edge[maxn*maxn];

int tt[maxn][maxn],ll[maxn][maxn];

int vis[maxn],len[maxn],pre[maxn],cnt[maxn],t[maxn];
void addedge(int u,int v,int len,int t)
{
	edge[tot].v=v;
	edge[tot].len=len;
	edge[tot].time=t;
	edge[tot].next=head[u];
	head[u]=tot++;
}
void dijkstra1()
{
	fill(vis,vis+maxn,0);
	fill(t,t+maxn,inf);
	fill(len,len+maxn,inf);
	for(int i=0;i<maxn;i++) pre[i]=i;
	
	t[s]=0;
	len[s]=0;
	pre[s]=s;
	for(int i=1;i<=n;i++)
	{
		int u=-1,Min=inf;
		for(int j=0;j<n;j++)
		{
			if(vis[j]==0&&t[j]<Min)
			{
				u=j;
				Min=t[j];
			}
		}
		
		vis[u]=1;
		
		for(int j=head[u];j!=-1;j=edge[j].next)
		{
			int v=edge[j].v;
			if(vis[v]) continue;
			if(t[v]>t[u]+edge[j].time)
			{
				t[v]=t[u]+edge[j].time;
				len[v]=len[u]+edge[j].len;
				pre[v]=u;
			}
			else if(t[v]==t[u]+edge[j].time&&len[v]>len[u]+edge[j].len)
			{
				t[v]=t[u]+edge[j].time;
				len[v]=len[u]+edge[j].len;
				pre[v]=u;
			}
		}				
	}	
}
void dijkstra2()
{
	fill(vis,vis+maxn,0);
	fill(len,len+maxn,inf);
	fill(cnt,cnt+maxn,inf);
	for(int i=0;i<maxn;i++) pre[i]=i;
	
	len[s]=0;
	cnt[s]=1;
	pre[s]=s;
	for(int i=1;i<=n;i++)
	{
		int u=-1,Min=inf;
		for(int j=0;j<n;j++)
		{
			if(vis[j]==0&&len[j]<Min)
			{
				u=j;
				Min=len[j];
			}
		}
		
		vis[u]=1;
		
		for(int j=head[u];j!=-1;j=edge[j].next)
		{
			int v=edge[j].v;
			if(vis[v]) continue;
			if(len[v]>len[u]+edge[j].len)
			{
				len[v]=len[u]+edge[j].len;
				cnt[v]=cnt[u]+1;
				pre[v]=u;
			}
			else if(len[v]==len[u]+edge[j].len&&cnt[v]>cnt[u]+1)
			{
				len[v]=len[u]+edge[j].len;
				cnt[v]=cnt[u]+1;
				pre[v]=u;
			}
		}				
	}	
}
int main()
{
	fill(head,head+maxn,-1);
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int u,v,t,len,time;
		cin>>u>>v>>t>>len>>time;
		if(t)
		{
			addedge(u,v,len,time);
		}
		else
		{
			addedge(u,v,len,time);
			addedge(v,u,len,time);
		}
	}
	cin>>s>>e; 
	int ans=0;
	dijkstra1();
//	cout<<t[3]<<endl;
	int Time=t[e];
	int strt[maxn];
	int k=e;
	while(1)
	{
		
		strt[ans++]=k;
		if(k==s) break;
		k=pre[k];	
	} 
//	cout<<str1;
	
	dijkstra2();
	
	int Len=len[e];
	int strl[maxn];
	int k1=e;
	int ans1=0;
	while(1)
	{
		
		strl[ans1++]=k1;
		if(k1==s) break;
		k1=pre[k1];	
	} 
//	cout<<len[e]<<" "<<str2;
	int flag=0;
	if(ans==ans1) 
	{
		for(int i=0;i<ans;i++)
		{
			if(strl[i]!=strt[i])
			{
				flag=1;
				break;
			}
		}
	}
	else flag=1;


	
	if(flag==0)
	{
		printf("Time = %d; ",Time);
		printf("Distance = %d: ",Len);
		
	//	cout<<"Time = "<<Time<<"; ";
	//	cout<<"Distance = "<<Len<<": ";
		for(int i=ans-1;i>=0;i--)
		{
			if(i==ans-1)
			printf("%d",strt[i]);
			//cout<<strt[i];
			else
			printf(" => %d",strt[i]);
		//	cout<<" => "<<strt[i];
		}
		return 0;
	}
	
	printf("Time = %d: ",Time);
	//cout<<"Time = "<<Time<<": ";
	for(int i=ans-1;i>=0;i--)
	{
		if(i==ans-1)
		printf("%d",strt[i]);
		//cout<<strt[i];
		else
		printf(" => %d",strt[i]);
		//cout<<" => "<<strt[i];
	}
	printf("\n");
	//cout<<endl;
	printf("Distance = %d: ",Len);
//	cout<<"Distance = "<<Len<<": ";
	for(int i=ans1-1;i>=0;i--)
	{
		if(i==ans1-1)
		printf("%d",strl[i]);
		//cout<<strl[i];
		else
		printf(" => %d",strl[i]);
		//cout<<" => "<<strl[i];
	}
	
}

不过上面的代码是我千辛万苦才修改对的,一个bug,找了整整一天
在这里插入图片描述
这是错误代码,bug仅仅在因为在输出路径时,我先用string把pre中的数字+‘0’转换为字符保存起来,但是这会有一个问题,就是如果数字大于等于10以后,就会出问题了,大家要以此为戒,千万不要在犯我这种错误了

#include<bits/stdc++.h>
using namespace std;
const int maxn=5000;
int head[maxn],tot=0;
int s,e,n,m;
const int inf=0x3f3f3f3f;
struct Edge{
	int v;
	int len,time,next;
	
}edge[maxn*maxn];

int tt[maxn][maxn],ll[maxn][maxn];

int vis[maxn],len[maxn],pre[maxn],cnt[maxn],t[maxn];
void addedge(int u,int v,int len,int t)
{
	edge[tot].v=v;
	edge[tot].len=len;
	edge[tot].time=t;
	edge[tot].next=head[u];
	head[u]=tot++;
}
void dijkstra1()
{
	fill(vis,vis+maxn,0);
	fill(t,t+maxn,inf);
	fill(len,len+maxn,inf);
	for(int i=0;i<maxn;i++) pre[i]=i;
	
	t[s]=0;
	len[s]=0;
	pre[s]=s;
	for(int i=1;i<=n;i++)
	{
		int u=-1,Min=inf;
		for(int j=0;j<n;j++)
		{
			if(vis[j]==0&&t[j]<Min)
			{
				u=j;
				Min=t[j];
			}
		}
		
		vis[u]=1;
		
		for(int j=head[u];j!=-1;j=edge[j].next)
		{
			int v=edge[j].v;
			if(vis[v]) continue;
			if(t[v]>t[u]+edge[j].time)
			{
				t[v]=t[u]+edge[j].time;
				len[v]=len[u]+edge[j].len;
				pre[v]=u;
			}
			else if(t[v]==t[u]+edge[j].time&&len[v]>len[u]+edge[j].len)
			{
				t[v]=t[u]+edge[j].time;
				len[v]=len[u]+edge[j].len;
				pre[v]=u;
			}
		}				
	}	
}
void dijkstra2()
{
	fill(vis,vis+maxn,0);
	fill(len,len+maxn,inf);
	fill(cnt,cnt+maxn,inf);
	for(int i=0;i<maxn;i++) pre[i]=i;
	
	len[s]=0;
	cnt[s]=1;
	pre[s]=s;
	for(int i=1;i<=n;i++)
	{
		int u=-1,Min=inf;
		for(int j=0;j<n;j++)
		{
			if(vis[j]==0&&len[j]<Min)
			{
				u=j;
				Min=len[j];
			}
		}
		
		vis[u]=1;
		
		for(int j=head[u];j!=-1;j=edge[j].next)
		{
			int v=edge[j].v;
			if(vis[v]) continue;
			if(len[v]>len[u]+edge[j].len)
			{
				len[v]=len[u]+edge[j].len;
				cnt[v]=cnt[u]+1;
				pre[v]=u;
			}
			else if(len[v]==len[u]+edge[j].len&&cnt[v]>cnt[u]+1)
			{
				len[v]=len[u]+edge[j].len;
				cnt[v]=cnt[u]+1;
				pre[v]=u;
			}
		}				
	}	
}
int main()
{
	fill(head,head+maxn,-1);
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int u,v,t,len,time;
		cin>>u>>v>>t>>len>>time;
		if(t)
		{
			addedge(u,v,len,time);
		}
		else
		{
			addedge(u,v,len,time);
			addedge(v,u,len,time);
		}
	}
	cin>>s>>e; 
	
	dijkstra1();
//	cout<<t[3]<<endl;
	int Time=t[e];
	string strt="";
	int k=e;
	while(1)
	{
		
		strt+=(k+'0');
		if(k==s) break;
		k=pre[k];	
	} 
//	cout<<str1;
	
	dijkstra2();
	
	int Len=len[e];
	string strl="";
	int k1=e;
	while(1)
	{
		
		strl+=(k1+'0');
		if(k1==s) break;
		k1=pre[k1];	
	} 
//	cout<<len[e]<<" "<<str2;

	
	if(strl==strt)
	{
		printf("Time = %d; ",Time);
		printf("Distance = %d: ",Len);
		
	//	cout<<"Time = "<<Time<<"; ";
	//	cout<<"Distance = "<<Len<<": ";
		for(int i=strt.size()-1;i>=0;i--)
		{
			if(i==strt.size()-1)
			printf("%c",strt[i]);
			//cout<<strt[i];
			else
			printf(" => %c",strt[i]);
		//	cout<<" => "<<strt[i];
		}
		return 0;
	}
	
	printf("Time = %d: ",Time);
	//cout<<"Time = "<<Time<<": ";
	for(int i=strt.size()-1;i>=0;i--)
	{
		if(i==strt.size()-1)
		printf("%c",strt[i]);
		//cout<<strt[i];
		else
		printf(" => %c",strt[i]);
		//cout<<" => "<<strt[i];
	}
	printf("\n");
	//cout<<endl;
	printf("Distance = %d: ",Len);
//	cout<<"Distance = "<<Len<<": ";
	for(int i=strl.size()-1;i>=0;i--)
	{
		if(i==strl.size()-1)
		printf("%c",strl[i]);
		//cout<<strl[i];
		else
		printf(" => %c",strl[i]);
		//cout<<" => "<<strl[i];
	}
	
}

不过,通过做这道题还是有点收获的,因为好久没写搜索的题目了,我自己都快忘记搜索怎么写了,尤其是深搜的如何传参和广搜的队列中储存什么,写完两个代码我发现,深搜dfs函数里面的参数就是通过一步步搜索,你需要的答案(当然在不考虑你定义全局变量的情况下),广搜队列中存储的也是这些答案,这就是他们的相似之处。而且,我总结了一下我以后如何写搜索,

  1. 首先,判断一下是否搜到了,没搜到了的话就继续搜
  2. 当然就是继续搜的过程了,继续向下搜的话 首先你要满足可以继续向下搜的条件,比如迷宫问题,你不可以越界,该店没走过、比如这道题,条件是你在搜到这里时这个点没有搜过才可以。
  3. 再然后你就需要在第二步的基础上注意一下回溯问题了,因为深搜是一条路走到底的过程,哪一条路在前面他就会先走那一条路,因此,之前搜索的不一定时最优的,你需要记录一下,通过比较更新找到最优的。在同一点,有许多条路可以走,你想再走其他路时,你就要清除之前走过路的影响,这就是回溯的时候清除影响,从而使搜的每一条路对应一个vis数组,对应一个这条路你要求的数据。而在广搜中,每一个入队列的结构体就相当于是一条独自的路,所以你只需要在结构体中开一个vis数组和一个记录数据的变量就和深搜的回溯一样了。
    而算法笔记上的广搜为什么就不用在结构体内部定义一个vis数组呢,应为那里是让你求最短路径的,你走的下一个节点不仅要你自己没有走过,比别人也要没有走过,不然,你这条路就不是最短的了。而这道天梯地图这道题是按边长的权值和,而不是把每个边的权值看作是1.
    我的dfs和bfs代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3;
int head[maxn],tot=0;
int s,e;
struct Edge{
	int v;
	int len,time,next;
	
}edge[maxn*maxn];
void addedge(int u,int v,int len,int time)
{
	edge[tot].v=v;
	edge[tot].len=len;
	edge[tot].time=time;
	edge[tot].next=head[u];
	head[u]=tot++;
}
string strl="";
int Len=99999999;
string strt="";
int lent=99999;
int Time=99999999;
class node{
public:
	int x;
 	string str;
	int len,time;	
	int vis[maxn];
	node()
	{
		fill(vis,vis+maxn,0);
	}
};
void bfs()
{
	queue<node>q;
	node t;
	t.x=s;
	t.len=0;
	t.time=0;
	t.str=s+'0';
	q.push(t);
	t.vis[s]=1;
	while(!q.empty())
	{
		t=q.front();
		q.pop();
		if(t.x==e)
		{
			
			if(t.time<Time||t.time==Time&&t.len<lent)
			{
				strt=t.str;
				Time=t.time;
				lent=t.len;
			}
			if(t.len<Len||Len==t.len&&strl.size()>t.str.size())
			{
				Len=t.len;
				strl=t.str;
			}			
		}
		int x=t.x;
		for(int i=head[x];i!=-1;i=edge[i].next)
		{
			int v=edge[i].v;
			if(t.vis[v]==0) 
			{
				node t1;
				t1=t;
				t1.str+=('0'+v);
				t1.time+=edge[i].time;
				t1.len+=edge[i].len;	
				t1.x=v;			
				t1.vis[v]=1;
				q.push(t1);
			//	dfs(v,ss,len+edge[i].len,time+edge[i].time);
			}
		}		
		
	}
	
}
int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);
//	cout.tie(0);
	int n,m;
	fill(head,head+maxn,-1);
	scanf("%d%d",&n,&m);
//	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int u,v,t,len,time;
		cin>>u>>v>>t>>len>>time;
		if(t)
		{
			addedge(u,v,len,time);
		}
		else
		{
			addedge(u,v,len,time);
			addedge(v,u,len,time);
		}
	}
	
	string str="";
	cin>>s>>e;	
	str+=(s+'0');	
		
	bfs();

	
	if(strl==strt)
	{
		printf("Time = %d; ",Time);
		printf("Distance = %d: ",Len);
		
	//	cout<<"Time = "<<Time<<"; ";
	//	cout<<"Distance = "<<Len<<": ";
		for(int i=0;i<strt.size();i++)
		{
			if(i==0)
			printf("%c",strt[i]);
			//cout<<strt[i];
			else
			printf(" => %c",strt[i]);
		//	cout<<" => "<<strt[i];
		}
		return 0;
	}
	
	printf("Time = %d: ",Time);
	//cout<<"Time = "<<Time<<": ";
	for(int i=0;i<strt.size();i++)
	{
		if(i==0)
		printf("%c",strt[i]);
		//cout<<strt[i];
		else
		printf(" => %c",strt[i]);
		//cout<<" => "<<strt[i];
	}
	printf("\n");
	//cout<<endl;
	printf("Distance = %d: ",Len);
//	cout<<"Distance = "<<Len<<": ";
	for(int i=0;i<strl.size();i++)
	{
		if(i==0)
		printf("%c",strl[i]);
		//cout<<strl[i];
		else
		printf(" => %c",strl[i]);
		//cout<<" => "<<strl[i];
	}
	
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3;
int head[maxn],tot=0;
int s,e;
struct node{
	int v;
	int len,time,next;
}edge[maxn*maxn];
void addedge(int u,int v,int len,int time)
{
	edge[tot].v=v;
	edge[tot].len=len;
	edge[tot].time=time;
	edge[tot].next=head[u];
	head[u]=tot++;
}
string strl="";
int Len=99999999;
string strt="";

int lent=99999;
int Time=99999999;
int vis[maxn];
void dfs(int x,string str,int len,int time)
{
	if(x==e)
	{	
	//	cout<<str<<" len "<<len<<" time "<<time<<endl;	
		if(time<Time||time==Time&&len<lent)
		{
			strt=str;
			Time=time;
			lent=len;
		}
		if(len<Len||Len==len&&strl.size()>str.size())
		{
			Len=len;
			strl=str;
		}		
	}
	for(int i=head[x];i!=-1;i=edge[i].next)
	{
		int v=edge[i].v;
		if(vis[v]==0) 
		{
			string ss=str;
			ss+=('0'+v);
			
			vis[v]=1;
			dfs(v,ss,len+edge[i].len,time+edge[i].time);
			vis[v]=0;
		}
	}
}
int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);
//	cout.tie(0);
	int n,m;
	fill(head,head+maxn,-1);
	scanf("%d%d",&n,&m);
//	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int u,v,t,len,time;
		cin>>u>>v>>t>>len>>time;
		if(t)
		{
			addedge(u,v,len,time);
		}
		else
		{
			addedge(u,v,len,time);
			addedge(v,u,len,time);
		}
	}
	
	string str="";
	cin>>s>>e;	
	str+=(s+'0');	
		
	vis[s]=1;
	dfs(s,str,0,0);

	
	if(strl==strt)
	{
		printf("Time = %d; ",Time);
		printf("Distance = %d: ",Len);
		
	//	cout<<"Time = "<<Time<<"; ";
	//	cout<<"Distance = "<<Len<<": ";
		for(int i=0;i<strt.size();i++)
		{
			if(i==0)
			printf("%c",strt[i]);
			//cout<<strt[i];
			else
			printf(" => %c",strt[i]);
		//	cout<<" => "<<strt[i];
		}
		return 0;
	}
	
	printf("Time = %d: ",Time);
	//cout<<"Time = "<<Time<<": ";
	for(int i=0;i<strt.size();i++)
	{
		if(i==0)
		printf("%c",strt[i]);
		//cout<<strt[i];
		else
		printf(" => %c",strt[i]);
		//cout<<" => "<<strt[i];
	}
	printf("\n");
	//cout<<endl;
	printf("Distance = %d: ",Len);
//	cout<<"Distance = "<<Len<<": ";
	for(int i=0;i<strl.size();i++)
	{
		if(i==0)
		printf("%c",strl[i]);
		//cout<<strl[i];
		else
		printf(" => %c",strl[i]);
		//cout<<" => "<<strl[i];
	}
	
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章