图论之图的遍历做题报告

来源:互联网 发布:linux中的ll 编辑:程序博客网 时间:2024/05/22 21:12

poj 3984 迷宫最短路
题意:二维5*5的迷宫,1表示墙壁,0表示路,不能横着竖着走,输出从左上角到右下角的最短路径。
想法:迷宫最短路且输出路径——bfs不完全赤果果的水题。但是难就难在怎么输出路径存储路径QAQ(用结构体).

#include <iostream>#include <queue>using namespace std;#define n 5int x,y;struct poi {     int px,py;//上一个节点的位置     int x,y;//此时节点的位置     int item; //该节点的值,即是路还是墙     int vis; //标记该点是否已被访问,1代表已被访问,0代表未被访问 };queue<poi> q;//定义一个面向整体的队列poi d[n][n];//申请一个结构体数组void bfs();void print(int rx,int ry);void bfs() {     poi head;//head的坐标一直变化     int dx,dy;//节点的位置     d[0][0].vis=1;  //初始化     q.push(d[0][0]);  //访问后弹出队列,访问下一个     while(!q.empty())     {         head=q.front();         q.pop();         for(int i=1;i<=4;i++) //四种方向下的可能,也可用存储-1,1,0,的数组操作            {                if(i==1)                {dx=head.x-1;dy=head.y;}                else if(i==2)                {dx=head.x+1;dy=head.y;}                else if(i==3)                {dy=head.y-1;dx=head.x;}                else                {dy=head.y+1;dx=head.x;}             if((dx<0)||(dy<0)||(dx>n)||(dy>n)||(d[dx][dy].item==1))            continue;//判断是否越界即小于零或超出维数或者该点为墙无法通过                if(!d[dx][dy].vis)                    {                       d[dx][dy].px=head.x;                       d[dx][dy].py=head.y;//把没被遍历过的这个点放在队首                       d[dx][dy].vis=1;                       q.push(d[dx][dy]);                    }                if((dx==n-1)&&(dy==n-1))                {                    print(dx,dy);                    return ;                }            }     }     return; }void print(int rx, int ry){    if((rx==0)&&(ry==0))    {        cout<<"("<<rx<<", "<<ry<<")"<<endl;        return;    }    print(d[rx][ry].px,d[rx][ry].py);//递归调用并传递该结点的上一个结点坐标    cout<<"("<<rx<<", "<<ry<<")"<<endl; //输出时记得都好后面有个空格    return;}int main(){    int i,j;    for(i=0;i<n;i++)    for(j=0;j<n;j++)    {   //初始化很重要        cin>>d[i][j].item;//0或者1        d[i][j].x=i;   //横坐标        d[i][j].y=j;//纵坐标        d[i][j].vis=0;        d[i][j].px=0;//入口的上个位置初始化为0        d[i][j].py=0;    }    while(!q.empty())q.pop(); //清空队列也很重要    bfs();    return 0;}

另一种用数组表示方向的代码,更简洁但是不易理解,来自这里写链接内容

#include<cstdio>#include<cstdlib>int map[5][5];int dir[4][2]={1,0,-1,0,0,1,0,-1};  //可走的四个方向struct pos{    int x,y;};struct pos queue[50],record[5][5];//queue记录可走的点,广搜;record记录改点的前驱void bfs(){       int head,tail,i;       struct pos cur,next;//cur为当前位置,next为下一个位置       head=tail=0;       cur.x=queue[tail].x;       cur.y=queue[tail].y;       tail++;       while(head<tail)       {              cur=queue[head++];              for(i=0;i<4;i++)              {                     next.x=cur.x+dir[i][0];                     next.y=cur.y+dir[i][1];                     if(next.x>=0&&next.y>=0&&next.x<5&&next.y<5&&map[next.x][next.y]==0)                     {                            record[next.x][next.y].x=cur.x;                            record[next.x][next.y].y=cur.y;//记录next的前驱,即next的坐标(因为next记录的是第一个到达该地点的前驱,随后被标记走过,故不用担心被后来的前驱坐标所覆盖)                            if(next.x==4&&next.y==4)                                   return ;                            else                            {                                   map[next.x][next.y]=1;//标记走过                                   queue[tail++]=next;                            }                     }              }       }}int main(){       int i,j,k,m,n;       struct pos cur;       for(i=0;i<5;i++)              for(j=0;j<5;j++)                     scanf("%d",&map[i][j]);       cur.x=0;       cur.y=0;       map[0][0]=1;       queue[0]=cur;       bfs();       k=0;       queue[k].x=4;       queue[k++].y=4;       i=j=4;       while(i!=0||j!=0)//根据record的记录,从后往前回溯其路径,并存在queue中       {              m=i;n=j;              i=record[m][n].x;              j=record[m][n].y;              queue[k].x=i;              queue[k++].y=j;       }       for(i=k-1;i>=0;i--)//输出路径              printf("(%d, %d)\n",queue[i].x,queue[i].y);       return 0;}

hdu 1241数油田
题意:一个矩阵里,如果油的相邻八个方向也是油,则属于一个油田,问有多少油田。
想法:求连接块啊——真的就是dfs赤果果的水题啊。

//以此点为中心,对周围的点进行遍历。#include <cstdio>#include <cstring>#include <iostream>using namespace std;int n,m,ans;int visit[102][102],dir[8][2] = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};char mat[102][102];void dfs(int a,int b){    visit[a][b] = 1;    for(int i=0; i<8; i++)    {        int xx = a+dir[i][0];        int yy = b+dir[i][1];        if(xx>=0&&xx<n&&yy>=0&&yy<m&&mat[xx][yy]=='@')        {            if(!visit[xx][yy])                dfs(xx,yy);        }    }}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        if(n==0&&m==0) break;        for(int i=0; i<n; i++)        {            for(int j=0; j<m; j++)                cin>>mat[i][j];        }        memset(visit,0,sizeof(visit));        ans = 0;        for(int i=0; i<n; i++)        {            for(int j=0; j<m; j++)                if(!visit[i][j]&&mat[i][j] == '@')                {                    dfs(i,j);                    ans++;                }        }        printf("%d\n",ans);    }    return 0;}

hdu 1312 数黑砖
题意:只能从黑砖走黑砖,红砖不能走,从@向四个方向走。求黑砖的个数(包括@)。
想法:深搜广搜肯定都能做,觉得深搜更好理解(乖巧)。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>int n,m,cnt;char map[30][30];int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};void dfs(int i,int j){    cnt++;    map[i][j]='#';    for(int k=0;k<4;k++)    {        int x=i+dir[k][0];        int y=j+dir[k][1];        if(x<n&&y<m&&x>=0&&y>=0&&map[x][y]=='.')            dfs(x,y);    }    return ;}int main(){    int fi,fj,i,j;    while(~scanf("%d %d%*c",&m,&n))    {        if(m==0&&n==0)break;        for(i=0;i<n;i++)        {                for(j=0;j<m;j++)            {                scanf("%c",&map[i][j]);                if(map[i][j]=='@')                {                    fi=i;                    fj=j;                }            }            getchar();        }        cnt=0;        dfs(fi,fj);        printf("%d\n",cnt);    }    return 0;}
0 0
原创粉丝点击