uva 208 Firetruck (需要预先处理 再dfs,TLE是此题AC常规步骤……)
来源:互联网 发布:最游记一键淘宝端 编辑:程序博客网 时间:2024/04/30 15:29
刚开始读完题目时感觉题目很常规,感觉就是很简单的连通图遍历,从起点遍历到终点,然后打印路径而已。
于是乎,用dfs理智的敲了一遍,然后TLE……
其实看到那么低的通过率就应该想到不会这么简单的。。不过对于一遍TLE这个伟大的事件,还是应该表扬一下,避免了走很多弯路。。
TLE之后马上就意识到这道题目不简单……一心想着自己的算法看来使用错了,一定会有大神用牛逼的算法来秒这道题!想着反正我的dfs没问题,算法错了让我如何是好!求知心切,就立马去看了其中的玄机……然后发现没有玄机。。就是在dfs之前先找出和终点连在一起的点将其记录下来,这样就可以避免dfs时会浪费大量的时间去回溯那些不可能到达终点的点了。大神管这个叫 “剪枝”。。。好吧,那我就学着 剪枝 了一下。。然后AC。。
为什么说这道题目好嘞?因为这道题目的亮点就在于为我提供了一条思路——当你dfs超时了,你该怎么办——剪枝!想各种办法剪枝!
而且这里还直接教了一种剪枝的办法,就实现从终点深搜一遍,找出能够到达终点的点,就能排除那些不必要的回溯时间。深搜不回溯,要比在没意义的点上不停地来来回回遍历要省时多了,根本不是一个数量级……
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <algorithm>using namespace std;int n;int G[25][25];int vis[25];int r[22];int ok[22],count_;int t1,t2,cnt;int route[100000][22];void dfs_init(int u){ ok[count_++]=u; vis[u]=1; for(int v=1;v<=21;v++) { if(G[u][v]&&!vis[v]) dfs_init(v); }}void dfs(int u){ vis[u]=1; if(u==n) { cnt++; memcpy(route[t2++],r,sizeof(r)); t1--; vis[u]=0; return; } for(int i=0;i<count_;i++) { int v=ok[i]; if(G[u][v]&&!vis[v]) { r[t1++]=v; G[u][v]=G[v][u]=0; dfs(v); G[u][v]=G[v][u]=1; } } vis[u]=0; t1--; return;}int main(){ int k=1; while(scanf("%d",&n)!=EOF) { memset(G,0,sizeof(G)); memset(route,0,sizeof(route)); int a1,a2; while(scanf("%d%d",&a1,&a2)!=EOF) { if(a1==0&&a2==0) break; G[a1][a2]=G[a2][a1]=1; } memset(vis,0,sizeof(vis)); count_=0; dfs_init(n); sort(ok,ok+count_); memset(vis,0,sizeof(vis)); t2=cnt=0; r[0]=1; t1=1; dfs(1); printf("CASE %d:\n",k++); for(int i=0;i<cnt;i++) { for(int j=0;route[i][j]!=n;j++) { printf("%d ",route[i][j]); } printf("%d",n); printf("\n"); } printf("There are %d routes from the firestation to streetcorner %d.\n",cnt,n); } return 0;}
其实上面的代码还有一个缺点,就是开了没有必要的大数组……,路劲根本就没有必要存下来,可以在dfs的时候直接输出来就好……浪费内存,也会浪费一部分时间、。。
向下面这样会很省内存,不用担心数组开小了,也不用担心内存不够。而且经验证真的会省不少时间,用时是上面的1/5……
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <algorithm>using namespace std;int n;int G[25][25];int vis[25];int r[22];int ok[22],count_;int t1,t2,cnt;void dfs_init(int u){ ok[count_++]=u; vis[u]=1; for(int v=1;v<=21;v++) { if(G[u][v]&&!vis[v]) dfs_init(v); }}void dfs(int u){ vis[u]=1; if(u==n) { cnt++; for(int i=0; i<t1-1; i++) { printf("%d ",r[i]); } printf("%d\n",n); t1--; vis[u]=0; return; } for(int i=0;i<count_;i++) { int v=ok[i]; if(G[u][v]&&!vis[v]) { r[t1++]=v; G[u][v]=G[v][u]=0; dfs(v); G[u][v]=G[v][u]=1; } } vis[u]=0; t1--; return;}int main(){ int k=1; while(scanf("%d",&n)!=EOF) { memset(G,0,sizeof(G)); int a1,a2; while(scanf("%d%d",&a1,&a2)!=EOF) { if(a1==0&&a2==0) break; G[a1][a2]=G[a2][a1]=1; } memset(vis,0,sizeof(vis)); count_=0; dfs_init(n); sort(ok,ok+count_); memset(vis,0,sizeof(vis)); t2=cnt=0; r[0]=1; t1=1; printf("CASE %d:\n",k++); dfs(1); printf("There are %d routes from the firestation to streetcorner %d.\n",cnt,n); } return 0;}
。哦,还有那个sort不能少的~否则不是字典序输出。
2 0
- uva 208 Firetruck (需要预先处理 再dfs,TLE是此题AC常规步骤……)
- UVA 208 FireTruck DFS
- UVA 208 Firetruck(DFS)
- UVa 208 Firetruck / dfs + floyd
- UVa 208 - Firetruck <双向DFS>
- UVa 208:Firetruck(DFS)
- uva 208 -Firetruck(dfs)
- UVA 208 Firetruck DFS 并查集
- UVA Firetruck (DFS)
- uva 208 Firetruck (DFS + 并查集)
- UVA 208 - Firetruck DFS 并查集剪枝
- UVa 208 - Firetruck(DFS判连通+回溯)
- Uva 208 Firetruck(dfs并查集优化)
- uva 208 - Firetruck
- uva 208 - Firetruck
- uva 208 - Firetruck
- UVa 208 - Firetruck
- UVA 208 - Firetruck
- ArcGlobe三维开发之十九——GlobeControl与MapControl的二三维联动
- hdu 3068 最长回文_Manacher模板
- Portlet通过标签在不同的模式(PortletMode)窗口状态间切换
- Unity将字符数组转换为字符串向Android传递消息
- static方法和static代码块区别
- uva 208 Firetruck (需要预先处理 再dfs,TLE是此题AC常规步骤……)
- UML学习总结
- jq 知识选择
- 算法实战学习之递归(1)
- SSH学习之一 OpenSSH基本使用
- 连载:面向对象葵花宝典:思想、技巧与实践(27) - 动态模型设计
- 类与对象
- try---catch---finally
- 未能加载文件或程序集“Newtonsoft.Json.Net35”或它的某一个依赖项。参数错误。 (异常来自 HRESULT:0x8007