2. 学会BFS与DFS
今天上午练习了一些简单的bfs和dfs,收获挺多的,越写越像模版题了~~
下午这个教室好像要用作考场擦擦擦
下午继续做bfs和dfs~
以下是题解:
hdu 1241:http://acm.hdu.edu.cn/showproblem.php?pid=1241
/*
dfs
从每一个@出发,count+1,dfs其八个方向,遇到@即将它置为*
*/
#include<iostream>
#define N 105
using namespace std;
int m,n;
char map[N][N];
int dx[8]={1,1,0,-1,-1,-1,0,1};
int dy[8]={0,1,1,1,0,-1,-1,-1};
bool check(int x,int y)
{
if(x>=0&&x<m&&y>=0&&y<n)
{
return true;
}
else
{
return false;
}
}
void dfs(int sx,int sy)
{
map[sx][sy]='*';
int x,y;
for(int i=0;i<8;i++)
{
x=sx+dx[i];
y=sy+dy[i];
if(check(x,y)&&map[x][y]=='@')
{
dfs(x,y);
}
}
}
int main()
{
while(cin>>m>>n,m!=0&&n!=0)
{
int count=0;
for(int i=0;i<m;i++)
{
cin>>map[i];
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(map[i][j]=='@')
{
count++;
dfs(i,j);
}
}
}
cout<<count<<endl;
}
system("pause");
return 0;
}
hdu 1242: http://acm.hdu.edu.cn/showproblem.php?pid=1242
/*
bfs模版题
先不继续做了
听会儿组合数学课!
*/
#include<iostream>
#include<queue>
using namespace std;
int n,m;
int i,j;
char map[205][205];
int visit[205][205];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
struct node
{
int x;
int y;
int step;
};
queue<node>q;
node s;
node next;
int check(int x, int y)
{
if(x < 0 || x > n || y < 0 || y > n||map[next.x][next.y]=='#')
return 0;
else
return 1;
}
void bfs()
{
int i;
while(!q.empty())
q.pop();
memset(visit, 0, sizeof(visit));
q.push(s);
visit[s.x][s.y] = 1;
while(!q.empty())
{
s = q.front();
q.pop();
if(map[s.x][s.y]=='r')
{
cout<<s.step<<endl;
return ;
}
if(map[s.x][s.y]=='x')
{
map[s.x][s.y]='.';
s.step++;
q.push(s);
}
else
{
for(i=0;i<4;i++)
{
next.x = dx[i] + s.x;
next.y = dy[i] + s.y;
next.step = s.step + 1;
if(!check(next.x, next.y))
continue;
if(!visit[next.x][next.y])
{
q.push(next);
visit[next.x][next.y] = 1;
}
}
}
}
cout<<"Poor ANGEL has to stay in the prison all his life."<<endl;
}//end of BFS()
int main()
{
while(cin>>n>>m)
{
memset(visit,0,sizeof(visit));
for(int i=0;i<n;i++)
{
getchar();
for(int j=0;j<m;j++)
{
cin>>map[i][j];
if(map[i][j]=='a')
{
s.x=i;
s.y=j;
s.step=0;
}
}
}
bfs();
}
system("pause");
return 0;
}
hdu 1312: http://acm.hdu.edu.cn/showproblem.php?pid=1312
/*
简单dfs
先判再搜
注意将@变为.
*/
#include<iostream>
using namespace std;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int n,m;
int cnt;
int sx,sy;
char map[25][25];
void dfs(int x,int y)
{
if(map[x][y]!='.'||x<0||x>=m||y<0||y>=n)
{
return ;
}
cnt++;
map[x][y]='#';
for(int i=0;i<4;i++)
{
int nextx=x+dx[i];
int nexty=y+dy[i];
dfs(nextx,nexty);
}
}
int main()
{
while(cin>>n>>m,n!=0&&m!=0)
{
cnt=0;
getchar();
for(int i=0;i<m;i++)
{
cin>>map[i];
// puts(map[i]);
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(map[i][j]=='@')
{
sx=i;
sy=j;
map[i][j]='.';
}
}
}
dfs(sx,sy);
cout<<cnt<<endl;
}
system("pause");
return 0;
}
hdu 1372: http://acm.hdu.edu.cn/showproblem.php?pid=1372
/*
简单bfs~
竟然得了一个output limit exceeded
原来是输入没有判定EOF。。。
*/
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
struct node
{
int x;
int y;
int step;
};
node s;
node next;
queue<node>q;
int dx[8]={2,1,-1,-2,-2,-1,1,2};
int dy[8]={1,2,2,1,-1,-2,-2,-1};
int sx,sy,ex,ey;
int visit[9][9];
char s1[5],s2[5];
int check(int x,int y)
{
if(x>=0&&x<8&&y>=1&&y<=8)
{
return 1;
}
else
{
return 0;
}
}
void bfs()
{
memset(visit,0,sizeof(visit));
while(!q.empty())
{
q.pop();
}
s.x=sx;
s.y=sy;
s.step=0;
visit[s.x][s.y]=1;
q.push(s);
while(!q.empty())
{
s=q.front();
q.pop();
if(s.x==ex&&s.y==ey)
{
printf("To get from %s to %s takes %d knight moves.\n",s1,s2,s.step);
return ;
}
for(int i=0;i<8;i++)
{
next.x=s.x+dx[i];
next.y=s.y+dy[i];
next.step=s.step+1;
if(!visit[next.x][next.y]&&check(next.x,next.y))
{
visit[next.x][next.y]=1;
q.push(next);
}
}
}
}
int main()
{
while(scanf("%s%s",s1,s2)!=EOF)
{
sx=s1[0]-'a';
sy=s1[1]-'0';
ex=s2[0]-'a';
ey=s2[1]-'0';
bfs();
}
system("pause");
return 0;
}
hdu 1072: http://acm.hdu.edu.cn/showproblem.php?pid=1072
/*
很有意义的bfs
这题wa了一次因为没有将map[i][j]=4的点在遍历后设为0(不可到达)
可以这样想
如果这个重置点可以多次进入的话,那么每次时间都会重设为6,然后又从该点进行同样的上下左右
方向的遍历,自然就进入死循环了。。。
*/
#include<iostream>
#include<queue>
using namespace std;
struct node
{
int x;
int y;
int step;
int time;
};
node s;
node next;
queue<node>q;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int map[9][9];
int n,m;
int sx,sy,ex,ey;
int check(int x,int y)
{
if(x>=0&&x<n&&y>=0&&y<m)
{
return 1;
}
else
{
return 0;
}
}
void bfs()
{
while(!q.empty())
{
q.pop();
}
s.x=sx;
s.y=sy;
s.step=0;
s.time=6;
q.push(s);
while(!q.empty())
{
s=q.front();
q.pop();
if(s.x==ex&&s.y==ey&&s.time>0)
{
cout<<s.step<<endl;
return ;
}
for(int i=0;i<4;i++)
{
next.x=s.x+dx[i];
next.y=s.y+dy[i];
next.step=s.step+1;
next.time=s.time-1;
if(check(next.x,next.y)&&map[next.x][next.y]!=0&&next.time>0)
{
if(map[next.x][next.y]==4)
{
map[next.x][next.y]=0;
next.time=6;
}
q.push(next);
}
}
}
cout<<"-1"<<endl;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>map[i][j];
if(map[i][j]==2)
{
sx=i;
sy=j;
}
if(map[i][j]==3)
{
ex=i;
ey=j;
}
}
}
bfs();
}
system("pause");
return 0;
}
hdu 1240: http://acm.hdu.edu.cn/showproblem.php?pid=1240
/*
三维bfs
一开始老是错
最后打印起始坐标发现输入不正确
三维的时候一定要注意输入的对应关系。。。
1A
*/
#include<iostream>
#include<queue>
using namespace std;
struct node
{
int x;
int y;
int z;
int step;
};
node s;
node next;
queue<node>q;
int dx[6]={1,0,-1,0,0,0};
int dy[6]={0,1,0,-1,0,0};
int dz[6]={0,0,0,0,1,-1};
char map[11][11][11];
int n;
int sx,sy,sz,ex,ey,ez;
int visit[11][11][11];
int check(int x,int y,int z)
{
if(x>=0&&x<n&&y>=0&&y<n&&z>=0&&z<n)
{
return 1;
}
else
{
return 0;
}
}
void bfs()
{
memset(visit,0,sizeof(visit));
while(!q.empty())
{
q.pop();
}
s.x=sx;
s.y=sy;
s.z=sz;
s.step=0;
visit[s.x][s.y][s.z]=1;
q.push(s);
while(!q.empty())
{
s=q.front();
q.pop();
if(s.x==ex&&s.y==ey&&s.z==ez)
{
printf("%d %d\n",n,s.step);
return ;
}
for(int i=0;i<6;i++)
{
next.x=s.x+dx[i];
next.y=s.y+dy[i];
next.z=s.z+dz[i];
next.step=s.step+1;
if(!visit[next.x][next.y][next.z]&&check(next.x,next.y,next.z)&&map[next.x][next.y][next.z]=='O')
{
visit[next.x][next.y][next.z]=1;
q.push(next);
}
}
}
printf("NO ROUTE\n");
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
char s1[10],s2[10];
char temp[10];
while(scanf("%s%s",s1,s2)!=EOF)
{
n=s2[0]-'0';
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
getchar();
for(int j=0;j<n;j++)
{
scanf("%c",&map[i][j][k]);
}
}
}
scanf("%d%d%d",&sx,&sy,&sz);
// printf("%c\n",map[sx][sy][sz]);
scanf("%d%d%d",&ex,&ey,&ez);
// printf("%c\n",map[ex][ey][ez]);
scanf("%s",temp);
bfs();
}
system("pause");
return 0;
}
hdu 1548: http://acm.hdu.edu.cn/showproblem.php?pid=1548
/*
bfs~
这个题又折腾了好久。。。
由于将n同时设为全局变量和局部变量导致传到bfs()里的n一直为0。。。。
*/
#include<iostream>
#include<queue>
using namespace std;
struct node
{
int x;
int step;
};
node s;
node next;
queue<node>q;
int start,end;
int map[205];
int visit[205];
int n;
int dx[2]={1,-1};
int check(int x)
{
if(x>=1&&x<=n)
{
// cout<<"hehe"<<endl;
return 1;
}
else
{
return 0;
}
}
void bfs()
{
memset(visit,0,sizeof(visit));
while(!q.empty())
{
q.pop();
}
s.x=start;
s.step=0;
visit[s.x]=1;
q.push(s);
while(!q.empty())
{
s=q.front();
q.pop();
if(s.x==end)
{
cout<<s.step<<endl;
return ;
}
for(int i=0;i<2;i++)
{
next.x=s.x+dx[i]*map[s.x];;
next.step=s.step+1;
// cout<<next.x<<endl;
// cout<<n<<endl;
// cout<<check(next.x)<<endl;
// cout<<visit[next.x]<<endl;
if(check(next.x)&&!visit[next.x])
{
q.push(next);
visit[next.x]=1;
}
}
}
cout<<"-1"<<endl;
}
int main()
{
while(cin>>n&&n!=0)
{
// cout<<n<<endl;
cin>>start>>end;
for(int i=1;i<=n;i++)
{
cin>>map[i];
}
bfs();
}
system("pasue");
return 0;
}
hdu 2181:http://acm.hdu.edu.cn/showproblem.php?pid=2181
/*
dfs
模版题
好好体会一下。。。
*/
#include<iostream>
using namespace std;
int map[25][3];
int visit[25];
int result[25];
int num=1;
int end;
void dfs(int m,int len)//从m出发的长度为len的序列
{
result[len]=m;
visit[m]=1;
for(int i=0;i<3;i++)
{
int temp=map[m][i];
if(temp==end&&len==19)
{
cout<<num++<<":"<<" ";
for(int j=0;j<20;j++)
{
cout<<result[j]<<" ";
}
cout<<end<<endl;
}
if(!visit[temp])
{
dfs(temp,len+1);
}
}
visit[m]=0;
}
int main()
{
for(int i=1;i<=20;i++)
{
cin>>map[i][0]>>map[i][1]>>map[i][2];
}
int m;
while(cin>>m&&m!=0)
{
end=m;
memset(visit,0,sizeof(visit));
dfs(m,0);
}
system("pause");
return 0;
}
hdu 2553: http://acm.hdu.edu.cn/showproblem.php?pid=2553
/*
dfs N皇后问题
感觉对dfs没有完全掌握。。。
自己写的时候总是弄不明白本质。。
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
struct point
{
int x,y;
}a[11];
int num,cnt;
int judge(int n,int x,int y)
{
int i;
for(i=0;i<n;i++){
if(a[i].y==y||abs(a[i].x-x)==abs(a[i].y-y))
return 0;
}
return 1;
}
void dfs(int n,int r)//按行dfs
{
int i;
if(n==num)
{
cnt++;
return;
}
for(i=1;i<=num;i++)
{
if(judge(n,r,i))
{
a[n].x=r;
a[n].y=i;
dfs(n+1,r+1);
}
}
return;
}
int main()
{
int ans[11];
for(num=1;num<11;num++)
{
cnt=0;
dfs(0,1);
ans[num]=cnt;
}
while(scanf("%d",&num),num)
printf("%d\n",ans[num]);
return 0;
}
dfs没有完全弄懂。。。
不过大体流程应该是:
判定是否到达目标条件->继续遍历其他结点
在以后遇到综合问题的时候再去深入学习吧~