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];
	}
	
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章