UVa 208 - Firetruck 回溯+剪枝 数据
/*这题上来没敢做,求最短路我会点,但是输出路径从来也没怎么考虑过,这次也算是遇到了吧!
这题也是图论的一种题,让你图中一点到所要求终点的所有路径!
*/
解题思路:
输入一个n,表示你所要到达的终点,紧接着是有边的两点,输入0 0时停止!
解题思路:
这题可以直接用邻接矩阵建图,(ps:邻接表暂时不是很熟练),DFS遍历图,找到所有路径,据网上众多题解所说,不进行优化会超时,(而我直接看过题解,直接优化了。所以没有超时的快感!),优化(剪枝)就是找到可以到达终点的点,优化方法据说有两种,一种可以用并查集,感觉太麻烦就直接舍弃了这种做法,另一种是弗洛伊德算法找到最短路,那么floyd之后图中如果某点和终点标记为0,那么可以知道这个点到不了终点。这题我的代码现在想想有点问题,但是是小问题,不妨碍 AC,具体是哪里,注释提到了。 具体DFS遍历见代码。
代码:
#include<iostream> #include <vector> #include <algorithm> #include <queue> #include<set> #include <cstdio> #include<iterator> using namespace std; int sum=0,n,max_; //n是你所要到达的终点,max_是你建图的最大边界值,这个一开始没注意这二者的区别,知道看见第二个样例突然明白,如果建图 1 2 3 4 5 6,而且你可以求起点到4的路径,而不是一定让你求1到6的路径。。 int a[1000][1000]= {0}; int floyd[100][100]; int vis[100]; int route[100]; int map_[100][100]; void init() { for (int i=0;i<100;i++) { for (int j=0;j<100;j++) { map_[i][j]=floyd[i][j]=0; //上面提到的问题就在于初始化,我应该把数组初始化为最大值INF或者一定比题目要求数据大的数,因为要求最短路啊,但是这里赋值为0也对额。 } } } void dfs(int x,int n1) // x代表从这个点走,n1表示路线长短, { //cout<<x<<"asd"<<endl; if (x==n) //如果这个点到了所要求的终点就输出回溯 { cout<<"1"; for (int i=1;i<n1-1;i++) { cout<<" "<<route[i]; }cout<<" "<<n<<endl; sum++; return ; } for(int i=1;i<=max_;i++) { if (!vis[i]&&floyd[n][i]&&map_[x][i]) { vis[i]=1; //标记路径, route[n1]=i; //保存路径, dfs(i,n1+1); //遍历下一个点,路径长度+1. vis[i]=0; //回溯解除标记、 } } } int main() { int k=0; while (cin>>n) { k++; sum=0; int a,b; init(); max_=0; while (cin>>a>>b&&(a+b)) { max_=max(max(a,b),max_); floyd[a][b]=floyd[b][a]=map_[a][b]=map_[b][a]=1; } for (int k=1;k<=max_;k++) //floyd求最短路。。。 { for (int i=1;i<=max_;i++) { for (int j=1;j<=max_;j++) { if(floyd[i][j]<floyd[i][k]+floyd[k][j]) { floyd[i][j]=floyd[i][k]+floyd[k][j]; } } } } vis[1]=1; printf("CASE %d:\n", k); dfs(1,1); printf("There are %d routes from the firestation to streetcorner %d.\n", sum, n); } }
PS:搜索还是嫩,只会初级的,这题算是开了眼界,弗洛伊德的用法也稍微拓展了些。还是要多练!!!
努力!强调:floyd算法用前一定初始化为INF,否则会很惨。