从零单排4

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没有完全弄懂。。。

不过大体流程应该是:

判定是否到达目标条件->继续遍历其他结点

在以后遇到综合问题的时候再去深入学习吧~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值