图的搜索和最短路径-Saving James Bond

来源:互联网 发布:报站软件 编辑:程序博客网 时间:2024/05/20 16:14

图的搜索-深度优先搜索DFS

  • 题目
    06-图2 Saving James Bond - Easy Version
  • 分析
    James从中心岛屿开始跳,这一跳需要进行特殊处理,然后在鳄鱼头上跳的时候,利用dfs进行搜索,一旦可以跳到安全区域就结束搜索。
    注意中心岛屿并不是P[0]。
  • 代码
#include<stdio.h>#include<math.h>#define maxn 101int N,D;int visited[maxn];int flag;struct point{    int x;    int y;}P[maxn];//求某个点与原点的距离的平方double distance1(int i){    return P[i].x * P[i].x + P[i].y * P[i].y;}//求某两个点之间的距离的平方double distance2(i, j){    return ((P[i].x-P[j].x)*(P[i].x-P[j].x) + (P[i].y-P[j].y)*(P[i].y-P[j].y));}int canSave(int i){    if(P[i].x-D <= -50 || P[i].x+D >= 50 || P[i].y-D <= -50 || P[i].y+D >= 50)        return 1;    return 0;}void dfs(int i){    //printf("%d\n",i);    visited[i] = 1;    if(canSave(i)){        flag = 1;        return;    }else{        int j;        for(j=0; j<N; j++){            if(!visited[j] && distance2(i,j)<=D*D){                dfs(j);            }            if(flag)    break;         }    }   }int main(){    flag = 0;    #ifndef ONLINE_JUDGE    freopen("save1.txt","r",stdin);    #endif    int i;    scanf("%d%d", &N,&D);    for(i=0; i<N; i++){        scanf("%d%d", &P[i].x, &P[i].y);        visited[i] = 0;    }    if(7.5+D >= 50) flag = 1;    if(!flag){        for(i=0; i<N; i++){            if(!visited[i] && (7.5+D)*(7.5+D)>=distance1(i)){                dfs(i);            }            if(flag)    break;              }    }    if(flag){        printf("Yes\n");    }else{        printf("No\n");    }    return 0;}

图的最短路径

  • 题目
    07-图5 Saving James Bond - Hard Version (30分)
  • 分析
    这道题是求一个单源无向无权重的图的最短路径问题,但不是普通意义上的最短路径,一般的最短路径是求一个顶点到其余各个顶点的最短路径,而这道题是求从中心点到跳出边缘的最短路径。
    需要注意的是:一是求最少跳数的最短路(bfs搜索,同时记录跳数)。二是要保存最短路径(用一个path[]数组来保存),三是当跳数相同时,最短路选择第一跳最短的那个路径(可以先根据第一跳的长度来排序)。
    上面这样做的话,其实找到的第一个可以跳出去的点,它的深度就是最短的跳数,此时就可以输出了。因为本身就是按照广度优先算法,第一个满足的点就是深度最小的。
  • 我的代码
#include<iostream>#include<algorithm>#include<stack> #include<queue>using namespace std;#define maxn 101int N,D;int dist[maxn];//P[0]表示原点,dist[i]表示P[i]到原点的最短距离 int path[maxn];//path[i]表示到P[0]的路上经过的顶点 int flag;int minPath = maxn;queue<int> Q;stack<int> S;struct point{    int x;    int y;}P[maxn];double distance1(int i){    return P[i].x * P[i].x + P[i].y * P[i].y;}double distance2(int i,int j){    return ((P[i].x-P[j].x)*(P[i].x-P[j].x) + (P[i].y-P[j].y)*(P[i].y-P[j].y));}int canSave(int i){    if(P[i].x-D <= -50 || P[i].x+D >= 50 || P[i].y-D <= -50 || P[i].y+D >= 50)        return 1;    return 0;}int comp(const point &a, const point &b){    if( (a.x * a.x + a.y * a.y) < (b.x * b.x + b.y * b.y))  return 1;    return 0;}int BFS(){    int tmpPath = 1,i;    for(i=1; i<=N; i++){        if(dist[i]==-1 && (7.5+D)*(7.5+D)>=distance1(i)){            Q.push(i);            dist[i] = 2;            //printf("%d\n", i);        }       }    while(!Q.empty()){        int tmp = Q.front();        Q.pop();        if(canSave(tmp)){            flag = 1;            minPath = dist[tmp];            int k;            for(k=0; k<minPath-1; k++){                S.push(tmp);                tmp = path[tmp];            }            break;        }        for(i=1; i<=N; i++){            if(dist[i]==-1 && distance2(tmp,i)<=D*D ){                dist[i] = dist[tmp] + 1;                path[i] = tmp;                Q.push(i);            }        }    }}int main(){    flag = 0;    #ifndef ONLINE_JUDGE    freopen("save2.txt","r",stdin);    #endif    int i;    scanf("%d%d", &N,&D);    for(i=1; i<=N; i++){        scanf("%d%d", &P[i].x, &P[i].y);        //visited[i] = 0;    }    sort(P+1, P+N+1, comp); //排序     for(i=1; i<=N; i++){        dist[i] = -1;        path[i] = -1;    }    if(7.5+D >= 50){        printf("1\n");        return 0;    }    BFS();    if(flag){        printf("%d\n",minPath);        for(i=0; i<minPath-1; i++){            int tmp;            tmp = S.top();            S.pop();            printf("%d %d\n", P[tmp].x, P[tmp].y);        }    }else{        printf("0\n");    }    return 0;}
原创粉丝点击