习题7-1:消防车(dfs+回溯)

来源:互联网 发布:sts格式化 javascript 编辑:程序博客网 时间:2024/04/30 12:39

习题7-1:消防车
题意:构造出一张图,给出一个点,字典序输出所有从1到该点的路径。
裸搜会超时的题目,其实题目的数据特地设计得让图稠密但起点和终点却不相连,所以直接搜索过去会超时。
只要判断下起点和终点能不能相连就行了,可以用并查集也可以用floyd算法,这样就能过了。
但是这个方法不是很完美的,如果两点之间只有一条线相连,而图又是稠密图,这样也很容易超时,数据强电就会挂掉。
可以把算法改进一下:是先从终点出发,无回溯的走遍和终点相连的所有点并标记,然后从起点出发,DFS判断下标记,这样就不会多走很多路了。另一个方法是在把点并入并查集的时候不考虑起点,然后DFS只走和终点同一集合的点。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int k, n, m, ans, maxn;bool Map[50][50];bool vis[50];bool floyd[50][50];int e[30];void dfs(int x, int d){    if(x == k)    {        printf("1");        for(int i = 1; i < d - 1; i++)        {            printf(" %d",e[i]);        }        printf(" %d\n",k);        ans++;        return;    }    for(int i = 1; i <= maxn; i++)    {        if(i == x)continue;        if(!vis[i] && Map[x][i] && floyd[i][k])        {            e[d] = i;            vis[i] = 1;            dfs(i, d + 1);            vis[i] = 0;        }    }}int main(){    int cases = 0;    while(scanf("%d",&k) != EOF)    {        int a, b;        maxn = 0;        memset(Map, 0, sizeof(Map));        memset(floyd, 0, sizeof(floyd));///忘记初始化导致超时        memset(vis, 0, sizeof(vis));        while(scanf("%d%d", &a, &b) && (a || b))        {            Map[a][b] = Map[b][a] = 1;            floyd[a][b] = floyd[b][a] = 1;            maxn = max(maxn, max(a, b));        }        for(int k = 1; k <= maxn; k++)            for(int i = 1; i <= maxn; i++)                for(int j = 1; j <= maxn; j++)                    floyd[i][j] = floyd[i][j] || (floyd[i][k] && floyd[k][j]);        ans = 0;        vis[1] = 1;        printf("CASE %d:\n",++cases);        dfs(1, 1);        printf("There are %d routes from the firestation to streetcorner %d.\n", ans, k);    }    return 0;}
原创粉丝点击