C语言BFS(5)___TT与魔法师(swust oj 2464)
Description
TT生活在一个充满魔法的国度,为了便于管理,国王请魔法师在一些重要的城市之间造出了“彩虹桥”!彩虹桥的特殊之处在于,可以从桥的一头瞬间移动到另一头。国王还请魔法师为彩虹桥设计出了通行证,通行证大致分成A,B,C三种,彩虹桥也对应A,B,C三种,每个彩虹桥可以识别的通行证最多为三种,每个人都拥有一个唯一类型的通行证,拥有通行证的人可以在对应的彩虹桥两头来回穿梭,如拥有A通行证的人只可以穿梭于可识别A通行证的彩虹桥。
一天,TT因为有急事需要从城市1穿梭到城市N,显然,一种类型的通行证可能不能使他顺利的从城市1到城市N。于是他请巫师帮忙看能不能设计一张万能的通行证,使他可以穿梭任意彩虹桥。巫师心力交瘁,终于设计出一种可以变换的通行证,这张通行证被巫师用魔法药水浸泡了七七四十九天,凝结了巫师的全部智慧,终于拥有了神奇的变换功能,使得它在每次使用以后会自动的变成另一种类型的通行证,变换的顺序为A->B->C->A…..如此循环。假设刚开始的类型为A。请你告诉TT如果他利用这张魔法卡片能不能顺利的从1点到N点。当然,由于每次传送都需要支付一定费用,所以在有多条路径存在的情况下,请选择花费最少的一条。
Input
第一行为测试的组数T,每组测试样例第一行输入2个数N,M代表N个城市之间有M条彩虹桥(1<=N<=1000,0<=M<=N*N)。接下来M行,每行四个数字S T L C(S!=T,1<=L<=1000,1<=C<=3)代表城市S和T之间(1<=S,T<=N)需要L的通行费和C型(为了方便,我们用1,2,3分别代表通行证A,B,C的类型)通行证(所有数字均是正整数)。
Output
如果TT能顺利的从城市1到城市N,输出最终的最小花费,否者输出-1
Sample Input
2
4 3
1 2 1 1
2 3 2 2
3 4 3 3
4 3
1 2 1 1
2 3 2 2
3 4 3 2
Sample Output
6
-1
#include <cstdio> #include <cstring> #include <vector> #include <iostream> #include <queue> #include <stdlib.h> using namespace std; int memory[1001][1001][4],n,m; int mpt[1001][1001][4],money[1001][1001][4]; bool book[1001][1001][4]; vector<int>way[1001]; int Min(int a,int b){ return (a>b)? b:a; } int dfs(int pre,int step,int k){ if(step==n)return 0; if(memory[pre][step][k])return memory[pre][step][k]; book[pre][step][k]=true; int i,ans=999999999; for(i=0;i<way[step].size();i++){ //cout<<step<<"→"<< way[step][i]<<endl; //printf("book[%d][%d]=%d\n",way[step][i],k%3+1,book[way[step][i]][k%3+1]); if(mpt[step][way[step][i]][k]==0 || book[step][way[step][i]][k%3+1]==true)continue; //cout<<step<<"→"<< way[step][i]<<" K:"<<k<<endl; ans=Min(ans,dfs(step,way[step][i],k%3+1)+money[step][way[step][i]][k]); } book[pre][step][k]=false; //printf("memort[%d][%d]=%d\n",step,k,ans); if(ans!=999999999) memory[pre][step][k]=ans; return ans; } void init(){ int i; for(i=0;i<1001;i++) way[i].clear(); memset(memory,0,sizeof(memory)); memset(money,0,sizeof(money)); memset(mpt,0,sizeof(mpt)); memset(book,0,sizeof(book)); } int main() { int i,j,v,u,k,w,t,ans; cin>>t; while(t--){ cin>>n>>m; init(); for(i=0;i<m;i++){ scanf("%d%d%d%d",&v,&u,&w,&k); if(mpt[v][u][1]==0 && mpt[v][u][2]==0 && mpt[v][u][3]==0){ way[v].push_back(u); way[u].push_back(v); } if(money[v][u][k]==0) money[v][u][k]=w,money[u][v][k]=w; else{ money[v][u][k]=Min(money[v][u][k],w); money[u][v][k]=Min(money[u][v][k],w); } mpt[u][v][k]=mpt[v][u][k]=1; } ans=dfs(0,1,1); if(ans!=999999999)printf("%d\n",ans); else printf("-1\n"); } return 0; }
#include <cstdio> #include <cstring> #include <vector> #include <iostream> #include <queue> #include <stdlib.h> using namespace std; struct node { int data,v,w; }; struct node1 { int step,v; }; int n,m; int visit[1001][4],dis[1001][4]; //visit数组是记录当前状态 [节点编号][通行证编号]是否在队列中. vector<node>mpt[1001]; void SPFA() { node1 s,e; int i,j,ss; queue<node1>team; s.step=1;s.v=1; team.push(s); visit[1][1]=1; while(team.size()){ //用队列中的状态去更新最小花费. s=team.front(); team.pop(); visit[s.step][s.v]=0; ss=mpt[s.step].size(); for(i=0;i<ss;i++){ if(mpt[s.step][i].v!=s.v)continue; if(dis[s.step][s.v]+mpt[s.step][i].w>=dis[mpt[s.step][i].data][s.v%3+1])continue; dis[mpt[s.step][i].data][s.v%3+1]=dis[s.step][s.v]+mpt[s.step][i].w; //松弛 if(visit[mpt[s.step][i].data][s.v%3+1]!=0)continue; e.step=mpt[s.step][i].data; e.v=s.v%3+1; visit[e.step][e.v]=1; team.push(e); } } int min=1999999999; for(i=1;i<4;i++)if(min>dis[n][i])min=dis[n][i]; if(min!=1999999999)cout<<min<<endl; else cout<<"-1"<<endl; } int main() { int i,j,t,x,y; cin>>t; while(t--){ cin>>n>>m; memset(visit,0,sizeof(visit)); for(i=1;i<=n;i++)for(j=0;j<4;j++)dis[i][j]=1999999999; dis[1][1]=0; for(i=0;i<1001;i++)mpt[i].clear(); for(i=0;i<m;i++){ node s; cin>>x>>y>>s.w>>s.v; s.data=x; mpt[y].push_back(s); s.data=y; mpt[x].push_back(s); } SPFA(); } return 0; }
如果有大神能用记忆化搜索做出来麻烦贴在下面的评论一下,万分感谢!!!!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。