kuangbin专题简单搜索:

 1:棋盘问题

 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

本题要注意任意两个棋子都不能放在棋盘中的同一列或者同一行,通过这句话我们可以将问题转化为从第一行开始,每行只放一个,并且与上面的棋子不在同一列,那么我们只要按照行或列每次遍历一行或者一列,然后DFS求出所有的可能。

假如按行遍历,我们就只需要标记哪一列被放过棋子。

这种题虽然简单但是按行搜索的方法却很巧妙

代码:

#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
#define fo(i,a,b) for(int i = a; i < b; i++) //宏定义 加快函数速度并简化函数写法
#define met(a,b) memset(a,0,sizeof(a));

char map[9][9];
int vis[9];  // 因为每次都是按行搜索,所以一定不在同一行,所以只需要标记列。 
int n, m, sum, num;

void print(){  // 棋盘输入
	met(map, 0);
	met(vis, 0);
	sum = 0, num = 0;
	fo(i, 0, n)
		fo(j, 0, n)
			cin>>map[i][j];	
}

void dfs(int x,int num){   
	if(num==m)
	{
		sum++;
		return ;	  //当棋子全部放入棋盘后,返回最后一层的上一层; 
	}
	fo(i, x, n)
	fo(j, 0, n){ 	
		if(map[i][j]=='#'&&!vis[j]){
			vis[j] = 1;
			dfs(i+1,num+1);  //  递归节点 
			vis[j] = 0;	     // 回溯节点 
		}
	} 
}

int main()
{
	while(cin>>n>>m&&n!=-1&&m!=-1){
		print();
	    dfs(0,0);
		cout<<sum<<endl; 
	}
	return 0;
 } 

2. Dungeon Master

 普通的BFS只不过从二维变成了三维,也就是多了两个上下的方向,

#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <math.h>
#include <queue> 
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define for(i,a,b) for(int i = a; i < b; i++)
struct node{
	int x,y,z;
	node(int x = 0, int y = 0, int z = 0):x(x), y(y), z(z){} 
};
queue <node> q;
int vis[33][33][33];
int step[33][33][33];
char map[33][33][33];
int nex[6][3] = {{0, 1, 0}, {1, 0, 0}, {0, 0, 1}, {0, 0, -1}, {0, -1, 0}, {-1, 0, 0}};
int L, R, C, sx, sy, sz, count1;
void init(){   // 输入
	met(vis, 0);
	met(map, 0);
	met(step, 0); 
	count1 = 0;
	while(!q.empty()) q.pop(); 
	for(l, 0, L)
		for(i, 0, R)
			for(j, 0, C){
				cin>>map[i][j][l];
				if(map[i][j][l] == 'S') {sx = i;  sy = j, sz = l;}
			}
}
void bfs(){
	node a;
	a.x = sx; a.y = sy; a.z = sz;
	q.push(a);
	while(!q.empty()){
		node b = q.front();
		q.pop();
		for(i, 0, 6){
			a.x = b.x + nex[i][0];
			a.y = b.y + nex[i][1];
			a.z = b.z + nex[i][2];
			if((map[a.x][a.y][a.z] == '.' || map[a.x][a.y][a.z] == 'E') && !vis[a.x][a.y][a.z]){
				vis[a.x][a.y][a.z] = 1;
				step[a.x][a.y][a.z] = step[b.x][b.y][b.z] + 1;
				if(map[a.x][a.y][a.z] == 'E'){count1 = 1; printf("Escaped in %d minute(s).\n",step[a.x][a.y][a.z]); return; }
				q.push(a);
			}
		}
	}
	return ;
}  
int main(){
	while(cin>>L>>R>>C,L, R, C){
		init();
		bfs();
		if(!count1) {cout<<"Trapped!"<<endl;}
	}
	return 0;
}

3.Catch That Cow

简单bfs

#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <queue>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
struct node{
	int x,step;
	node(int x=0, int step=0):x(x), step(step){}
};
int N,K;
int vis[1000002];
void bfs(){
	memset(vis, 0, sizeof(vis));
	queue <node> q;
	node a;
	a.x = N;
	a.step=0;
	q.push(a);
	vis[a.x] = 1;
	while(!q.empty()){
		node r = q.front();
		q.pop();
		for(int i = 0; i < 3; i++){
			if(i==0){
				a.x = r.x + 1;
				if(!vis[a.x]&&a.x>=0&&a.x<=100000){
					a.step=r.step+1,q.push(a),vis[a.x]=1;
					if(a.x==K) {cout<<a.step<<endl;return;}	
				}				
			}
			if(i==1){
				a.x = r.x - 1;
				if(!vis[a.x]&&a.x>=0&&a.x<=100000) {
					a.step=r.step+1,q.push(a),vis[a.x]=1;
					if(a.x==K) {cout<<a.step<<endl;return;}
				} 
			}
			if(i==2){
				a.x = r.x * 2;
				if(!vis[a.x]&&a.x>=0&&a.x<=100000){
					a.step=r.step+1,q.push(a),vis[a.x]=1;
					if(a.x==K) {cout<<a.step<<endl;return;}
				}
			}
		}
	}
	return ;
} 
int main(){
	cin >> N >> K ;
	if(N==K) cout<<"0"<<endl;
	else bfs();
	 
	return 0;
} 

4. Fliptile  (开关问题+二进制搜索) 每一个位置的改变可以影响周围4个方向,如果按行或列来看的话,这一行以上就只有上一行能影响到下一行,可以简化问题,所以我们可以枚举出第一行所有的情况,然后从第二行开始,让第一行变白。然后直到最后一行,如果最后一行也是白色,则将反转情况的数组存起来,更新反转次数更小的,最后输出。

#include <iostream>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define fo(i,a,b) for(int i = a; i < b; i++)
int map[20][20];
int cal[20][20];
int Min[20][20];
int n,m;
int nxt[5][2] = {{0,0},{0,1},{0,-1},{1,0},{-1,0}};
int getc(int x,int y){       //(x,y)的状态由本身的黑白 + 周围五个的翻转状态决定
    int t = map[x][y];
    for(int i = 0;i < 5;i ++){
        int nx = x + nxt[i][0];
        int ny = y + nxt[i][1];
        if(nx < 1 || nx > n || ny < 1 || ny > m) continue;
        t += cal[nx][ny];
    }
    return t%2;
}
int dfs(){
    for(int i = 2; i <= n; i++)
        for(int j = 1;j <= m;j ++)
            if(getc(i-1,j)) cal[i][j] = 1;    //如果上方为黑色,必须要翻转
    for(int i = 1; i <= m; i++)      //最后一行全白
        if(getc(n,i))  return -1;
    int t = 0;
    for(int i = 1;i <= n;i ++)
        for(int j = 1;j <= m;j ++)
            t += cal[i][j];
    return t;
}
 
int main()
{
    while(cin>>n>>m){
        for(int i = 1;i <= n; i++)
            for(int j = 1;j <= m; j++)
                cin>>map[i][j];
        int flag = 0, ans = -1;
        for(int i = 0;i < 1<<m; i++){       //第一行 1<<m种状态,二进制从0开始,字典序从小到大
            memset(cal,0,sizeof(cal));
            for(int j = 1;j <= m; j++)      //利用二进制枚举第一行所有的情况
                cal[1][m-j+1] = i>>(j-1) & 1;
            int cont = dfs();
            if(cont >= 0 &&(cont < ans || ans<0)){        //翻转次数最少
                flag = 1;
                ans = cont;
                memcpy(Min,cal,sizeof(cal));
            }
        }
        if(!flag)   cout<<"IMPOSSIBLE"<<endl;
        else{
            for(int i = 1;i <= n;i ++){
                for(int j = 1;j <= m;j ++){
                    if(j != 1)  cout<<" ";
                    cout<<Min[i][j];
                }
                cout<<endl;
            }
        }
    }
    return 0;
}

5.Find The Multiple

 long long 可以存下最大答案,简单BFS

#include <stdio.h>
#include <string>
#include <iostream> 
#include <string.h>
#include <queue> 
using namespace std;
#define ll long long
int x;
void bfs(){
	queue<ll> q;
	q.push(1);
	while(!q.empty()){
		ll b = q.front();
		q.pop();
		if(b % x == 0) {cout<<b<<endl; return;} 
		for(int i = 0; i < 2; i++){
			if(i == 0){	ll a = b*10 + 0; q.push(a);}
			else      { ll a = b*10 + 1; q.push(a);}	
		}	 	
	}
}
int main(){
	while(cin>>x,x){
		bfs();
	}
	return 0;
}

6.Prime Path

将一个数变为一个素数,每次改变一位,且改变后该数仍为素数。求最少操作次数,那BFS肯定是跑不掉了。

可以提前将所有四位数的素数打表,然后就可以直接查询了。

每次遍历某一位的所有情况,将所有符合条件的数加入队列。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
#include <math.h> 
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define fo(i,a,b) for(int i = a; i < b; i++)
int vis[10000];
int A[10000]={0};
int x, y;
bool flag;
typedef pair <int, int> P;
bool sushu(int a){
	for(int i = 2; i < a/2+1 ;i++)
		if(a%i==0) return false;   
	return true; 
}
void FindA(){
	for(int i = 999; i<9999;i+=2){	
		if(sushu(i)){
			A[i] = 1;	
		}
	}
	return ;
}
void solve(int sum,int &A, int &B, int &C, int &D){
	D = sum / 1000;
	C = sum /100 %10;
	B = sum /10 %10;
	A = sum %10;
	return ;
}
void bfs(){
	flag=false;
	for(int i = 1000; i <= 9999; i+=1)
		vis[i] = 0;
	queue <P> q;	
	q.push(P(x,0));
	vis[x] = 1;
	while(!q.empty()){	
		P p = q.front();
		q.pop();
		int ONE,TEN,HUN,TND; 	
		solve(p.first,ONE,TEN, HUN, TND);
		if(p.first == y) {cout<<p.second<<endl; flag=true; return;} 
		
		//qian
		for(int j = 1; j <= 9; j++){
			P pp;
			pp.first = j*1000 + HUN*100 + TEN*10 + ONE; 	
//			if(pp.first==y) {cout << p.second+1 <<endl;flag=true;return;}
			if(A[pp.first]&&!vis[pp.first]) {pp.second=p.second+1;q.push(pp);vis[pp.first]=1;}
		}
		//bai
		for(int j = 0; j <= 9; j++){
			P pp;
			pp.first = TND*1000 + j*100 + TEN*10 + ONE;
//			if(pp.first==y) {cout << p.second+1 <<endl;flag=true;return;}
			if(A[pp.first]&&!vis[pp.first]) {pp.second=p.second+1;q.push(pp);vis[pp.first]=1;}				
		}
		//shi
		for(int j = 0; j <= 9; j++){
			P pp;
			pp.first = TND*1000 + HUN*100 + j*10 + ONE;
//			if(pp.first==y) {cout << p.second+1 <<endl;flag=true;return;}
			if(A[pp.first]&&!vis[pp.first]) {pp.second=p.second+1;q.push(pp);vis[pp.first]=1;}				
		}
		//ge
		for(int j = 0; j <= 9; j++){
			P pp;
			pp.first = TND*1000 + HUN*100 + TEN*10 + j;
//			if(pp.first==y) {cout << p.second+1 <<endl;flag=true;return;}
			if(A[pp.first]&&!vis[pp.first]) {pp.second=p.second+1;q.push(pp);vis[pp.first]=1;}
		}				
	}
	return ;
}
int main(){
	int T;
	FindA();
	cin>>T;
	while(T--)
	{
		cin>>x>>y;
		bfs();
		if(flag==false)
			cout << "Impossible\n";
	}
	return 0;
}

7. Shuffle'm Up

牌的最底部是 S[0];

暴力模拟,然后把出现过的字符加入map数组中,如果有重复,则退出,输出 -1;

#include <cstdio>
#include <iostream>
#include <queue>
#include <string>
#include <map>
#include <set> 
using namespace std;
int main(){
	int T;
	cin>>T;
	for(int i = 0; i < T; i++){
		map <string,int> S;
		int m,cnt = 0;
		cin>>m;
		string s,s1,s2,s3="";  // s + s1 ->  s2
		cin>>s>>s1>>s2;
		while(1){ 
			s3="";
			cnt++;
			for(int i = 0; i < m; i++){
				s3 =s3 + s1[i] + s[i];
			}
			if(S[s3]) {cnt = -1;break;} 
			if(s3==s2) {break;} 
			else{
				S[s3] = 1;
				s = s3.substr(0,m);
				s1  = s3.substr(m,m);
			}
		}
		cout<<i+1<<" "<<cnt<<endl; 
	}
	return 0;
}

 8.Pots

 倒水问题,关键是将所有瓶中的水看做一个状态,然后模拟倒水就行了。

这个题还要存储一下上一次倒水的值,倒序查找路径,保存后倒序输出路径。

#include <stdio.h>
#include <string>
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define fo(i,a,b) for(int i = a; i < b; i++)
struct node{
	int a,b,step;
};
int vis[110][110];
node l[110][110];
int A,B,C,flag = 0;
node cnt;
void bfs(){
	queue <node> q;
	node nx;
	nx.a = 0;
	nx.b = 0;
	nx.step = 0;
	l[nx.a][nx.b].a = 0;
	l[nx.a][nx.b].b = 0; 
	q.push(nx);
	while(!q.empty()){
		node r = q.front();
		q.pop();
		if(r.a==C||r.b==C) {flag = 1; cout<<r.step<<endl; cnt.a = r.a; cnt.b = r.b; return ;} 
		if(r.a!=A){ //  装满 A
			nx.a = A;
			nx.b = r.b;
			if(!vis[nx.a][nx.b]){
				vis[nx.a][nx.b] = 1;
				l[nx.a][nx.b].a = r.a;
				l[nx.a][nx.b].b = r.b;
				nx.step = r.step + 1;
				q.push(nx);
			}
		}
		if(r.b!=B){ // 装满 B 
			nx.a = r.a;
			nx.b = B;
			if(!vis[nx.a][nx.b]){
				vis[nx.a][nx.b] = 1;
				l[nx.a][nx.b].a = r.a;
				l[nx.a][nx.b].b = r.b;
				nx.step = r.step + 1;
				q.push(nx);
			}
		} 
		if(r.a){ // 倒掉 A 
			nx.a = 0;
			nx.b = r.b;
			if(!vis[nx.a][nx.b]){
				vis[nx.a][nx.b] = 1;
				l[nx.a][nx.b].a = r.a;
				l[nx.a][nx.b].b = r.b;
				nx.step = r.step + 1;
				q.push(nx);
			}	
		} 
		if(r.b){ // 倒掉 B 
			nx.b = 0;
			nx.a = r.a;
			if(!vis[nx.a][nx.b]){
				vis[nx.a][nx.b] = 1;
				l[nx.a][nx.b].a = r.a;
				l[nx.a][nx.b].b = r.b;
				nx.step = r.step + 1;
				q.push(nx);
			}
		} 
		if(r.a&&r.b!=B){ // 将 A -> B  
			int x = r.a + r.b;
			if(x<=B) {nx.b = x; nx.a = 0;}
			else {nx.b = B; nx.a = x - B;}
			if(!vis[nx.a][nx.b]){
				vis[nx.a][nx.b] = 1;
				l[nx.a][nx.b].a = r.a;
				l[nx.a][nx.b].b = r.b;
				nx.step = r.step + 1;
				q.push(nx);
			} 
		} 
		if(r.b&&r.a!=A){ // 将 B - > A 
			int x = r.a + r.b;
			if(x<=A) {nx.a = x; nx.b = 0;}
			else {nx.a = A; nx.b = x - A;}
			if(!vis[nx.a][nx.b]){
				vis[nx.a][nx.b] = 1;
				l[nx.a][nx.b].a = r.a;
				l[nx.a][nx.b].b = r.b;
				nx.step = r.step + 1;
				q.push(nx);
			} 
		}
	}
	cout<<"impossible\n";
	return ;
}
void print(){
	if(flag){
		node x[100000];
		int i = cnt.a;
		int j = cnt.b;
		int k = 1;
		x[0].a = i;
		x[0].b = j; 
		while(i!=0||j!=0){ 
			x[k].a = l[i][j].a;
			x[k].b = l[i][j].b;
			int t = i;
			i = l[i][j].a;
			j = l[t][j].b;
			k++;
		}
		for(int i = k-1; i>0; i--){
//			cout<<x[i].a<<"  "<<x[i].b<<"   "<<x[i-1].a<<"  "<<x[i-1].b<<endl;
			if(x[i-1].a-x[i].a==0&&x[i-1].b-x[i].b!=0){
				if(x[i-1].b==B){
					cout<<"FILL(2)\n";
				}
				else if(x[i-1].b==0)
					cout<<"DROP(2)\n";
			}
			else if(x[i-1].a-x[i].a!=0&&x[i-1].b-x[i].b==0){
				if(x[i-1].a==A){
					cout<<"FILL(1)\n";
				}
				else if(x[i-1].a==0)
					cout<<"DROP(1)\n";
				}
			else if(x[i-1].a-x[i].a!=0&&x[i-1].b-x[i].b!=0){
				if(x[i-1].a-x[i].a>0&&x[i].b-x[i-1].b>0) // b -> a;
					cout<<"POUR(2,1)\n";
				else if(x[i].a-x[i-1].a>0&&x[i-1].b-x[i].b>0) // a - > b;
					cout<<"POUR(1,2)\n";	
			}	
		}
	}
}
int main(){
	while(cin>>A>>B>>C){
		flag = 0;
		memset(vis,0,sizeof(vis));
		memset(l,0,sizeof(l));
		vis[0][0] = 1;
		bfs();
		print();
	}
	return 0;	
}

9.Fire Game 

判断能否把草烧完,输出最小时间, 有两个起始点,输入时把草的数量存起来,然后BFS,求出BFS中遍历到的草的数量,和总共的草的数量比较,如果不等于,则输出-1;

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define fo(i,a,b) for(int i = a; i < b; i++) 
char map[15][15];
int vis[15][15];
int nxt[4][2] = {0,1,1,0,0,-1,-1,0};
int n,m;
struct node{
	int x,y,step;
	node(int x = 0,int y = 0, int step = 0):x(x),y(y),step(step){} 
}Arr[100];	
int k;
int minnt = 0;
void init(){
	k = 0;
	met(Arr,0);
	fo(i,0,n){
		fo(j,0,m)
		{	
			cin>>map[i][j];
			if(map[i][j] == '#'){ Arr[k].x = i; Arr[k].y = j; k++;} 	
		}
	}	
}
int bfs(int x, int y, int x1, int y1){
	met(vis,0);
	vis[x][y] = 1;
	vis[x1][y1] = 1;
	int cnt = 0;
	queue <node> q;
	node nx, nx1;
	nx.x = x;	nx.y = y;
	nx1.x = x1;	nx1.y = y1;
	q.push(nx);
	q.push(nx1);
	if(x==x1&&y==y1) cnt = 1;
	else cnt = 2; 
	while(!q.empty()){
		node r = q.front();
		q.pop();
		for(int i=0;i<4;i++){
			nx.x = r.x + nxt[i][0];
			nx.y = r.y + nxt[i][1];
			if(nx.x<0||nx.x>=n||nx.y<0||nx.y>=m) continue;
			if(!vis[nx.x][nx.y]&&map[nx.x][nx.y]=='#'){
				vis[nx.x][nx.y] = 1;
				nx.step = r.step + 1;
				minnt = nx.step;	
				cnt++;
				q.push(nx);
			}
		}
	} 
	if(cnt == k){
		return 1;
	}
	else return 0;
}
int main(){
	int T,count = 0;
	cin>>T;
	while(T--){
		count++;
		cin>>n>>m;
		init();
//		fo(i,0,k) cout<<Arr[i].x<<"   "<<Arr[i].y<<endl; 
		int minn = -1;
		for(int i = 0; i < k; i++)
			for(int j = i; j < k; j++){
				if(bfs(Arr[i].x,Arr[i].y,Arr[j].x,Arr[j].y)&&(minn>minnt||minn==-1))
					minn = minnt;
			}
		if(k<=2) minn = 0;	
		cout<<"Case "<<count<<": "<<minn<<endl;
	}
	return 0;
} 

10.Fire!

先对火进行BFS,然后记录每个点火蔓延到的时间,然后对人进行BFS,BFS时判断人到某点的时间是否比火早,如果不比火早则不能通过。

#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
#define fo(i,a,b) for(int i = a; i < b; i++)
#define met(a,b) memset(a,b,sizeof(a));
typedef struct Point{
	int x,y;
	Point(int x=0, int y=0):x(x),y(y){} 
}Point;
int nex[4][2]={0, 1, 1, 0, 0, -1, -1, 0};
char map[1010][1010];
int vis[1010][1010];  
int timef[1010][1010],timej[1010][1010]; 
int n, m, x, y, x1, y1;
queue <Point> q;

void Fbfs(){
	met(vis, 0); 
	met(timef, 0);
	while(!q.empty()){
		Point a = q.front();
		vis[a.x][a.y] = 1;
		q.pop();
		fo(i, 0, 4){
			Point b;
			b.x = a.x + nex[i][0];
			b.y = a.y + nex[i][1];
			if(map[b.x][b.y] =='.'&&!vis[b.x][b.y]&&b.x>=0&&b.x<n&&b.y>=0&&b.y<m){
				vis[b.x][b.y] = 1;
				timef[b.x][b.y] = timef[a.x][a.y] + 1;  // 向外扩展的层数 
				q.push(b);
			} 
		}
	}
	return;	
}

int Jbfs(){
	met(vis, 0);
	met(timej, 0);
	vis[x][y] = 1; 
	Point a;
	a.x = x;
	a.y = y;
	q.push(a);
	while(!q.empty()){
		Point b = q.front();
		q.pop();
		fo(i, 0, 4){
			a.x = b.x + nex[i][0];
 			a.y = b.y + nex[i][1];
 			if(a.x<0||a.y<0||a.x>=n||a.y>=m){
 				printf("%d\n",timej[b.x][b.y]+1);
			 	return 0;
			 }
			else if(map[a.x][a.y]=='.'&&(timef[a.x][a.y]>timej[b.x][b.y]+1||timef[a.x][a.y]==0)&&!vis[a.x][a.y]){
				vis[a.x][a.y] = 1;    //注意判断条件 (timef[a.x][a.y]>timej[b.x][b.y]+1||timef[a.x][a.y]==0) 火走不到或者人走到这一步时,火走不到 
				timej[a.x][a.y] = timej[b.x][b.y] + 1;	// 向外扩展的层数 
				q.push(a);
			} 
		}
	}
	printf("IMPOSSIBLE\n");
	return 0;
}

void print()
{
	while(!q.empty())
		q.pop();
	met(map, 0);
	fo(i, 0, n){
		fo(j, 0, m)
		{
			scanf("%c",&map[i][j]);
			if(map[i][j]=='F'){ 
				Point c;
				c.x = i;
				c.y = j;
				q.push(c); //将所有火的坐标都进队,同时进行BFS向外层层扩展 
			}
			if(map[i][j]=='J'){
				x = i;
				y = j;
			} 
		 }
		 getchar(); 
	}
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d", &n, &m);
		getchar();
		print();
		Fbfs();
		Jbfs();
	}
		return 0;
}

11.迷宫问题

简单BFS,但需要输出路径,正着搜索输出路径很麻烦,但这道题可以倒着搜索,会方便一点。

#include <iostream>
#include <string>
#include <string.h>
#include <queue>
using namespace std;
#define met(a,b) memset(a,0,sizeof(a))
#define fo(i,a,b) for(int i = a; i < b; i++)
int nex[4][2] = {-1,0,0,-1,0,1,1,0};
int map[5][5];
int vis[5][5];
struct node{
	int x,y;
}n[5][5];
void init(){
	met(vis, 0);
	met(map, 0);
	fo(i, 0, 5)
		fo(j, 0, 5)
			cin>>map[i][j]; 
}
void bfs(){
	queue <node> q; 
	node a;
	a.x = 4; a.y = 4;
	q.push(a);
	while(!q.empty()){
		node b = q.front(); q.pop(); 
		fo(i, 0, 4){
			a.x = b.x + nex[i][0];
			a.y = b.y + nex[i][1];
			if(map[a.x][a.y]==0&&!vis[a.x][a.y]&&a.x>=0&&a.x<5&&a.y>=0&&a.y<5){
				q.push(a); 
				vis[a.x][a.y] = 1; 
				n[a.x][a.y].x = b.x; 
				n[a.x][a.y].y = b.y; 
			}
			if(a.x==0&&a.y==0) return; 
		}
	} 
}
int main()
{
	init();
	bfs();
	int i = 0, j = 0;
	while(1){
		cout<<"("<<i<<", "<<j<<")"<<endl;
		if(i==4&&j==4) return 0;
		int ii = i;
		i = n[i][j].x;
		j = n[ii][j].y;
	}
	return 0;
}

12.DFS求连通块数量.

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
using namespace std;
char map[110][110];
int vis[110][110];
int nxt[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
int n,m;
void init(){
	memset(vis,0,sizeof(vis));
	memset(map,0,sizeof(map));
	for(int i = 0; i < n; i++){
		scanf("%s",map[i]);
		getchar();
	}
}
void dfs(int x, int y){
	for(int i = 0; i < 8; i++){
		int nx = x + nxt[i][0];
		int ny = y + nxt[i][1];
		if(!vis[nx][ny]&&nx>=0&&nx<n&&ny>=0&&ny<m){
			vis[nx][ny] = 1;
			if(map[nx][ny]=='@') dfs(nx, ny);	
		} 
	}
}
int main(){
	while(cin>>n>>m,n,m){
		getchar();
		init();
		int cnt = 0;
		for(int i = 0; i < n; i++){
			for(int j = 0; j < m; j++){
				if(!vis[i][j]&&map[i][j]=='@'){
					vis[i][j] = 1;
					dfs(i,j);
					cnt++;
					}
				}
			}
		cout<<cnt<<endl;
	}
	return 0;
}

13.非常可乐

倒水问题. 将三个瓶中水的体积作为一个状态,然后BFS模拟倒水。(倒水时只考虑两个瓶子)

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
using namespace std;
struct node{
	int s,n,m,step; 
};
int S,N,M;
int vis[105][105][105];
void bfs(){
	memset(vis,0,sizeof(vis));
	vis[S][0][0] = 1;
	node s;
	s.s = S; s.n = 0; s.m = 0; s.step = 0;
	queue <node> q;
	q.push(s);
	while(!q.empty()){
		node r = q.front();
		q.pop();
		if(r.s==S/2&&r.m==S/2){ cout<<r.step<<endl; return;}
		if(r.s&&r.m!=M){ // s -> M;
			int c = r.m + r.s;
			if(c<=M) {s.s = 0; s.m = r.m + r.s; s.n = r.n;} 
			else {s.s = c - M; s.m = M; s.n = r.n;}
			if(!vis[s.s][s.n][s.m])
			{
				s.step = r.step + 1;
				vis[s.s][s.n][s.m] = 1;
				q.push(s);
			}
		}
		if(r.s&&r.n!=N){ // s -> N;
			int c = r.n + r.s;
			if(c<=N) {s.s = 0; s.n = r.n + r.s; s.m = r.m;} 
			else {s.s = c - N; s.n = N; s.m = r.m;}
			if(!vis[s.s][s.n][s.m])
			{
				s.step = r.step + 1;
				vis[s.s][s.n][s.m] = 1;
				q.push(s);
			}
		}
		if(r.n&&r.s!=S){ // N -> S ;
			s.s = r.n+r.s; s.n = 0; s.m = r.m; 
			if(!vis[s.s][s.n][s.m])
			{
				s.step = r.step + 1;
				vis[s.s][s.n][s.m] = 1;
				q.push(s);
			}
		}
		if(r.n&&r.m!=M){ // N - > M;
			int c = r.m + r.n;
			if(c<=M) {s.s = r.s; s.m = r.m + r.n; s.n = 0;} 
			else {s.s = r.s; s.m = M; s.n = c - M;}
			if(!vis[s.s][s.n][s.m])
			{
				s.step = r.step + 1;
				vis[s.s][s.n][s.m] = 1;
				q.push(s);
			}
		}
		if(r.m&&r.s!=S){ // M - > S
			s.s = r.s + r.m; s.m = 0; s.n = r.n;
			if(!vis[s.s][s.n][s.m])
			{
				s.step = r.step + 1;
				vis[s.s][s.n][s.m] = 1;
				q.push(s);
			}
		}
		if(r.m&&r.n!=N){ //M - > N;
			int c = r.m + r.n;
			if(c<=N) {s.s = r.s; s.n = r.m + r.n; s.m = 0;} 
			else {s.s = r.s; s.n = N; s.m = c - N;}
			if(!vis[s.s][s.n][s.m])
			{
				s.step = r.step + 1;
				vis[s.s][s.n][s.m] = 1;
				q.push(s);
			}
		}
	}
	cout<<"NO"<<endl;
	return; 
}
int main(){
	while(scanf("%d%d%d",&S,&N,&M),S||N||M){
		if(N>M){
			int t = N;
			N = M;
			M = t;
		}
		if(S%2!=0){
			cout<<"NO\n";
			continue;
		}
		else
			bfs();	
	}
	return 0;
} 

14.进行两次BFS,分别记录两个人到达KFC的时间,然后求出两个人到达同一个KFC的最小时间.

#include <stdio.h>
#include <iostream>
#include <queue>
#include <string>
#include <string.h>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define for(i,a,b) for(int i=a;i<b;i++)
#define INF 1e9
struct Point{
	int x,y;
	Point(int x=0, int y=0):x(x),y(y){} 
}; 
char map[202][202];
int vis[202][202];
int nex[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
int x,y,xx,yy,n,m;
int a[202][202];
int b[202][202];
queue <Point> q;
void print(){
	met(map, 0);
	met(vis, 0);
	met(a, 0);
	met(b, 0);
	for(i, 0, n){ 
		for(j, 0, m){
			scanf("%c",&map[i][j]);
			if(map[i][j] == 'Y')
				x = i, y = j;
			else if(map[i][j]=='M')
				xx = i, yy = j;	 
		} 
		getchar(); 
	} 
//	for(i, 0, n) 
//	{
//			for(j, 0, m)
//			cout<<map[i][j];
//			cout<<endl;
//	}	
}
void Bfs(int x,int y,int num[202][202]){
	vis[x][y] = 1;
	Point t;
	t.x = x;
	t.y = y;
	q.push(t);
	while(!q.empty()){
		Point r = q.front();
		q.pop();
		for(i, 0, 4){
			t.x = r.x + nex[i][0];
			t.y = r.y + nex[i][1];
			if(map[t.x][t.y] == '#'||t.x<0||t.x>=n||t.y<0||t.y>=m||vis[t.x][t.y])
				continue;
			else{
				vis[t.x][t.y] = 1;
				q.push(t);
				num[t.x][t.y] = num[r.x][r.y] + 1;
			}	
		}
	}
}

void slove(){
	int minn = INF;
	for(i, 0, n)
	{
		for(j, 0, m){
			if(map[i][j] == '@'&&a[i][j]!=0&&b[i][j]!=0)
			minn = min(minn, a[i][j]+b[i][j]);
		}
	}
	cout<<minn*11<<endl;	 
}
int main()
{	
	while(scanf("%d%d",&n,&m)!=EOF){
		getchar();
		print();
		Bfs(x, y, a);
		met(vis, 0);
		Bfs(xx, yy, b);
		slove();
	}	
	return 0;
}
发布了52 篇原创文章 · 获赞 114 · 访问量 6019

猜你喜欢

转载自blog.csdn.net/GD_ONE/article/details/100833175