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);
    }
}
View Code

 

PS:搜索还是嫩,只会初级的,这题算是开了眼界,弗洛伊德的用法也稍微拓展了些。还是要多练!!!

努力!强调:floyd算法用前一定初始化为INF,否则会很惨。

posted @ 2017-05-05 22:27  飞将-奉先  阅读(162)  评论(0编辑  收藏  举报