BFS~~~迷宫

例题1:NYOJ 58(最小步数),保存每一步的步数即可,至于标程中是另外一种算法,后面的讨论个人觉得对这个代码的评价不好,因为标程中涉及到的是另外一种算法,不是说他不会用BFS进行广搜,他只是想告诉你这道题用Floyd-Warshall算法可用,不多说了,纯属个人言谈~~用BFS的时候记得把map放在main里面。

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int num,dx[4]={0,1,0,-1},dy[4]={-1,0,1,0};
class point{
public:
    int x,y,step;
    friend istream& operator>>(istream &input,point &P)
    {   input>>P.x>>P.y; 
        return input;
    }    
    bool operator==(point &P) const
    {   return x==P.x&&y==P.y;
    }             
}Start,End;
bool Inside(point p)
{   return p.x>=0&&p.x<9&&p.y>=0&&p.y<9; 
}
int BFS(int map[9][9])
{   queue<point> Q;
    point New,temp;
    Q.push(Start);
    map[Start.x][Start.y]=1;
    while(!Q.empty())
    {   temp=Q.front();
        Q.pop();
        if(temp==End) break;
        for(int i=0;i<4;i++)
        {   New.x=temp.x+dx[i];
            New.y=temp.y+dy[i];
            if(Inside(New)&&map[New.x][New.y]==0)
            {   map[New.x][New.y]=1;
                New.step=temp.step+1;
                Q.push(New);         
            }
        }
    }
    return temp.step;
}

int main()
{   cin>>num;
    while(num--)
    {   int map[9][9]={ 
            1,1,1,1,1,1,1,1,1,
            1,0,0,1,0,0,1,0,1,
            1,0,0,1,1,0,0,0,1,
            1,0,1,0,1,1,0,1,1,
            1,0,0,0,0,1,0,0,1,
            1,1,0,1,0,1,0,0,1,
            1,1,0,1,0,1,0,0,1,
            1,1,0,1,0,0,0,0,1,
            1,1,1,1,1,1,1,1,1
        };
        cin>>Start>>End;
        Start.step=0;
        cout<<BFS(map)<<endl;
    }
    return 0;
}

下面为标准程序:

#include<iostream> 
#include<cmath> 
using namespace std; 
int mz[9][9]={ 
    1,1,1,1,1,1,1,1,1, 
    1,0,0,1,0,0,1,0,1, 
    1,0,0,1,1,0,0,0,1, 
    1,0,1,0,1,1,0,1,1, 
    1,0,0,0,0,1,0,0,1, 
    1,1,0,1,0,1,0,0,1, 
    1,1,0,1,0,1,0,0,1, 
    1,1,0,1,0,0,0,0,1, 
    1,1,1,1,1,1,1,1,1 
}; 
inline int ABS(int a) 
{   return a>0?a:-a; 
} 
int len[10][10][10][10]; 
const int INF=100000; 
void FloydWarshall() 
{   for(int i=1;i!=8;i++) 
        for(int j=1;j!=8;j++) 
            for(int k=1;k!=8;k++) 
                for(int l=1;l!=8;l++) 
                    if(i==k && j== l) len[i][j][k][l]=0; 
                    else if(mz[i][j]==0 && mz[k][l]==0 && ABS(i-k)+ABS(j-l)==1) len[i][j][k][l]=1; 
                    else len[i][j][k][l]=INF; 
    int v=49; 
    for(int k=1;k!=8;k++) 
        for(int l=1;l!=8;l++)             
            for(int m=1;m!=8;m++) 
                for(int n=1;n!=8;n++) 
                    for(int i=1;i!=8;i++) 
                        for(int j=0;j!=8;j++) 
                            if(len[m][n][i][j]>len[m][n][k][l]+len[k][l][i][j]) len[m][n][i][j]=len[m][n][k][l]+len[k][l][i][j]; 
} 
int main() 
{   FloydWarshall(); 
    int n,a,b,c,d; 
    cin>>n;    
    while(n--)    
    {   cin>>a>>b>>c>>d;        
        cout<<len[a][b][c][d]<<endl;   
    }
    return 0;  
}

例题2:NYOJ 92,题目不难,就是要注意输入,先输入宽,再输入高。把图外边围一圈不是0的数再BFS搜就可以了,代码:

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX1=1450;
const int MAX2=970;
int num,wid,high;
int dx[4]={0,1,0,-1},dy[4]={-1,0,1,0};
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int map[MAX2][MAX1];
struct point
{   int x,y;
}Start;
queue<point> Q;
bool Inside(point p)
{   return  p.x>=0&&p.x<=high+1&&p.y>=0&&p.y<=wid+1;
}
void BFS(int x,int y)
{   point New,start;
    start.x=x,start.y=y;
    Q.push(start);
    while(!Q.empty())
    {   start=Q.front();
        Q.pop();
        for(int i=0;i<4;i++) 
        {   New.x=start.x+dx[i];
            New.y=start.y+dy[i];
            if(Inside(New)&&map[New.x][New.y]!=0)
            {   map[New.x][New.y]=0;
                Q.push(New);
            }
        }
    }
}
int main()
{   scanf("%d",&num);
    while(num--)
    {   scanf("%d%d",&wid,&high);
        CLR(map,-1);
        for(int i=1;i<=high;i++)
            for(int j=1;j<=wid;j++)
                scanf("%d",&map[i][j]);
        BFS(0,0);
        for(int i=1;i<=high;i++)
        {   printf("%d",map[i][1]);
            for(int j=2;j<=wid;j++)
                printf(" %d",map[i][j]);
            printf("\n");        
        }
    }
    return 0;
}

例题3:NYOJ 284,就是要注意一点,当有砖块的时候,你只能用子弹打掉这块砖块将它做空地方处理,继续BFS,而不能我一打掉这块砖块就直接通过这个地方。

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=350;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int n,m,dx[4]={0,1,0,-1},dy[4]={-1,0,1,0},visit[MAX][MAX];
char map[MAX][MAX];
struct point{
    point(){x=y=step=0;}
    point(int a,int b,int c):x(a),y(b),step(c){}
    bool operator==(point p) const {return x==p.x&&y==p.y;}   
    int x,y,step;
}Start,End;
queue<point> Q;
bool Inside(point p)
{   return p.x>=0&&p.x<n&&p.y>=0&&p.y<m; 
}
void BFS()
{   point temp,New;
	Q.push(Start);
	visit[Start.x][Start.y]=1;
    while(!Q.empty())
	{   temp=Q.front();
	    if(temp==End) break;
		Q.pop();
		if(map[temp.x][temp.y]=='B')
		{   temp.step++;
			Q.push(temp);
			map[temp.x][temp.y]='E';
            //只能先把这块砖先打掉,而不能打掉后直接通过这个地方,因为打掉这块砖后要把这个地方当做Empty来看,重新搜索 
		}
		else 
		for(int i=0;i<4;i++)
		{   New.x=temp.x+dx[i];
			New.y=temp.y+dy[i];
			char c=map[New.x][New.y];
			if(!visit[New.x][New.y]&&Inside(New)&&c!='S'&&c!='R')
			{   New.step=temp.step+1;
			    Q.push(New);
			    visit[New.x][New.y]=1;
			}
		}
    }
	if(Q.empty()) printf("-1\n");
	else  printf("%d\n",temp.step);
}
int main()
{   while(scanf("%d%d",&n,&m),n||m)
	{   getchar();
        CLR(visit,0);
		while(!Q.empty()) Q.pop();//不要把这个清空的放在最后面去了,WA了n次啊 
        for(int i=0;i<n;i++) gets(map[i]);
        for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
			{   if(map[i][j]=='Y') Start.x=i,Start.y=j;
				if(map[i][j]=='T') End.x=i,End.y=j;
			}
		BFS();
	}
	return 0;
}

例题4:NYOJ 27(水池数目),这个是要求个数,解释不清楚,直接看代码吧:

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
const int MAX=101;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int n,m,total,map[MAX][MAX];
int dx[4]={0,1,0,-1},dy[4]={-1,0,1,0};
struct Point 
{   int x,y; 
};
bool Inside(Point P)
{   return P.x>=0&&P.x<n&&P.y>=0&&P.y<m;
}
void BFS(int x,int y)
{   queue<Point> Q;
    Point s,New;
    s.x=x,s.y=y;
    Q.push(s);
    while(!Q.empty())
    {   s=Q.front();
        Q.pop();
        for(int i=0;i<4;i++)
        {   New.x=s.x+dx[i];
            New.y=s.y+dy[i];
            if(Inside(New)&&map[New.x][New.y]==1)
            {   map[New.x][New.y]=0;
                Q.push(New);
            }
        } 
    } 
    total++;
}
int main()
{   int Case,value;
    scanf("%d",&Case);
    while(Case--)
    {   scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) 
            for(int j=0;j<m;j++)
                {   scanf("%d",&value);
                    map[i][j]=value;
                }
        total=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(map[i][j]) BFS(i,j);
        printf("%d\n",total);            
    }
    return 0;
}

例题5:NYOJ 523(亡命逃窜),没有多大改变,就是变成三维的了,没有什么要注意的,就是数据量比较大,用cin,cout会超时,改成scanf,printf输入输出就可以了。

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio> 
using namespace std;
const int MAX=51;
int A,B,C,Time,map[MAX][MAX][MAX];
int dx[6]={-1,0,1,0,0,0},dy[6]={0,1,0,-1,0,0},dz[6]={0,0,0,0,1,-1};
struct Point
{   int x,y,z,step;
    bool operator==(const Point& P) const
    {   return x==P.x&&y==P.y&&z==P.z; 
    } 
};
Point Start,End;
bool Inside(Point P)
{   return P.x>=0&&P.x<A&&P.y>=0&&P.y<B&&P.z>=0&&P.z<C;
}
int BFS()
{   queue<Point> Q;
    Point s,New;
    Q.push(Start);
    map[Start.x][Start.y][Start.x]=1; 
    while(!Q.empty())
    {   s=Q.front();
        Q.pop();
        if(s==End&&s.step<=Time) return s.step; 
        for(int i=0;i<6;i++)
        {   New.x=s.x+dx[i];
            New.y=s.y+dy[i];
            New.z=s.z+dz[i]; 
            if(Inside(New)&&map[New.x][New.y][New.z]==0)
            {   map[New.x][New.y][New.z]=1;
                New.step=s.step+1;
                Q.push(New); 
            }
        }
    }
    return 0;
}
int main()
{   int Case,flag;
    scanf("%d",&Case); 
    while(Case--)
    {   scanf("%d%d%d%d",&A,&B,&C,&Time);
        Start.x=0,Start.y=0,Start.z=0,Start.step=0;
        End.x=A-1,End.y=B-1,End.z=C-1; 
        for(int i=0;i<A;i++)
            for(int j=0;j<B;j++)
                for(int k=0;k<C;k++)
                {   scanf("%d",&flag);
                    map[i][j][k]=flag;
                }  
        flag=BFS();   
        if(flag) printf("%d\n",flag);
        else printf("-1\n"); 
    }
    return 0;
}

嗯,最后一个题型了,马的遍历,POJ 2243(马的遍历),记住加visit[][],剪枝防止超时,找到马的跳跃过程中坐标的变化情况即可。

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
const int MAX=10;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int visit[MAX][MAX];
int dx[8]={-2,-1,1,2,2,1,-1,-2},dy[8]={1,2,2,1,-1,-2,-2,-1};
struct Point 
{   int x,y,step;
    bool operator==(const Point &P) const
    {   return P.x==x&&P.y==y;
    }
};
Point Start,End;
bool Inside(Point P)
{   return P.x>=1&&P.x<9&&P.y>=1&&P.y<9;
}
int BFS()
{   queue<Point> Q;
    Point s,New;
    Q.push(Start);
    while(!Q.empty())
    {   s=Q.front();
        Q.pop();
        if(s==End) return s.step;
        for(int i=0;i<8;i++)
        {   New.x=s.x+dx[i];
            New.y=s.y+dy[i];
            if(Inside(New)&&!visit[New.x][New.y])
            {   New.step=s.step+1;
                visit[New.x][New.y]=1; 
                Q.push(New);
            }
        }    
    }
}
int main()
{   char S[10],E[10];
    while(scanf("%s %s",S,E)!=EOF)
    {   CLR(visit,0);
        Start.x=S[0]-'a'+1,Start.y=S[1]-'0',Start.step=0;
        End.x=E[0]-'a'+1,End.y=E[1]-'0';
        visit[Start.x][Start.y]=1; 
        printf("To get from %s to %s takes %d knight moves.\n",S,E,BFS());
    }
    return 0;
}

 



 

你可能感兴趣的:(c,算法,struct,Class,ini,input)