kuangbin topic 1. Search (low order)

Posted by Ashley Sheridan on Fri, 10 Sep 2021 03:04:21 +0200

A - chessboard problem
https://vjudge.ppsucxtt.cn/contest/65959#problem/A
Idea: whether dfs searches for different rows and columns, the main steps are the marking and release order of vis array.

#include <iostream>
#include <stdio.h> 
#define MAX 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 10;
int n, k, sum;
char mp[maxn][maxn]; //Save map 
int vis[maxn];//Tag array 
void dfs(int x, int y){
	if(y==0){ //When the number of pieces to be put is 0, the number of schemes + 1, sum++ 
		sum++;
		return;
	}
	if(x>n) return; //It's possible that dfs goes to x > N, which returns directly 
	for(int i=1; i<=n; i++){
		if(!vis[i]&&mp[x][i]=='#'){
			vis[i]=1;//Tag with columns 
			dfs(x+1,y-1);
			vis[i]=0;//Release the tag. Great. Reset the tag directly 
		}
	}
	if(x+1<=n) dfs(x+1,y);//This is to prevent the situation that there is no one # on the first floor 
}
int main(){
	while(cin>>n>>k&&n!=-1&&k!=-1){
		for(int i=1; i<=n; i++) scanf("%s",mp[i]+1);//A new input method 
		sum=0;
		dfs(1,k);
		cout << sum << endl;
	}
	return 0;
}

B-Dungeon Master
Title Link

#include <iostream>
#include <queue>
#include <stdio.h>
#include <cstring>
#define MAX 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 35;
int l, r, c;
char mp[maxn][maxn][maxn];
int dx[6]={1,-1,0,0,0,0};//The direction array can be written separately 
int dy[6]={0,0,1,-1,0,0};
int dz[6]={0,0,0,0,1,-1};
int dis[maxn][maxn][maxn];//Used to record the number of steps taken to reach the current point 
struct node{
	int x, y, z; //Auxiliary structure 
};
queue <node> q;
node st, sf, ans, cnt;
int bfs(node st, node sf){
	memset(dis,-1,sizeof(dis)); //Multiple inputs, so reset 
	q.push(st);
	dis[st.x][st.y][st.z]=0; //First set to 0, so that all steps are expanded, and - 1 is the point that has not been reached to realize the function of marking array 
	while(!q.empty()){
		ans=q.front();
		q.pop();
		for(int i=0; i<6; i++){
			int tx=ans.x+dx[i], ty=ans.y+dy[i], tz=ans.z+dz[i];
			//Here is the implementation of bfs 
			if(tx>=1&&tx<=l&&ty>=1&&ty<=r&&tz>=1&&tz<=c&&dis[tx][ty][tz]==-1&&mp[tx][ty][tz]=='.'){
				node cnt;
				cnt.x=tx, cnt.y=ty, cnt.z=tz;
				q.push(cnt);
				dis[tx][ty][tz]=dis[ans.x][ans.y][ans.z]+1;
			}
		}
	}
	return dis[sf.x][sf.y][sf.z];
}
int main(){
	while(scanf("%d%d%d",&l,&r,&c)&&l!=0&&r!=0&&c!=0){
		for(int i=1; i<=l; i++){
			for(int j=1; j<=r; j++){
				for(int k=1; k<=c; k++){
					cin >> mp[i][j][k];//Don't use scanf to input, No 
				}
			}
		}
		for(int i=1; i<=l; i++){
			for(int j=1; j<=r; j++){
				for(int k=1; k<=c; k++){
					if(mp[i][j][k]=='S'){
						st={i,j,k};
					}
					if(mp[i][j][k]=='E'){
						sf={i,j,k};
						mp[i][j][k]='.';//Be sure to set the end point to '.' so that you can get the last number of steps, otherwise it will always be - 1 
					}
				}
			}
		}
		int res=bfs(st,sf);
		if(res!=-1) printf("Escaped in %d minute(s).\n",res);
		else printf("Trapped!\n");
	}
	return 0;
}



C-Catch That Cow (bfs find the shortest idea)
Title Link

#include <iostream>
#include <stdio.h>
#include <queue>
using namespace std;
const int maxn = 1e5+10;
int n, k;
struct node{
	int x;
	int sum;
};//Auxiliary structure 
queue <node> q;
int vis[maxn]; //This problem must have a marked array, otherwise it will always fall into an endless loop and calculate a position repeatedly, and you won't get the result 
int bfs(int n, int k){
	node ans, ansx, cnt;
	ans.x=n, ans.sum=0;
	q.push(ans);
	vis[ans.x]=1;
	while(!q.empty()){
		cnt=q.front();
		q.pop();//bfs must remember to leave the team 
		if(cnt.x==k) return cnt.sum;
		for(int i=1; i<=3; i++){
			if(i==1) ansx.x=cnt.x+1;
			if(i==2) ansx.x=cnt.x-1;
			if(i==3) ansx.x=cnt.x*2;
			if(ansx.x>=0&&ansx.x<=100000&&!vis[ansx.x]){
				ansx.sum=cnt.sum+1;
				vis[ansx.x]=1;
				q.push(ansx);
			}
		}
	}
}
int main(){
	scanf("%d%d",&n,&k);
	printf("%d",bfs(n,k));
	return 0;
}

D-maze problem
Title Link

#include <iostream>
#include <vector>
#include <queue>
#include <stdio.h>
using namespace std;
typedef pair<int,int> pii;
int mp[6][6];
int vis[6][6];
int dir[4][2]={-1,0,1,0,0,-1,0,1};
int road[6][6][2];
vector <pii> v;
queue <pii> q;
void bfs(int x, int y){
	vis[x][y]=1;
	q.push({0,0});
	while(!q.empty()){
		int a=q.front().first, b=q.front().second;
		q.pop();
		if(a==4&&b==4){
			int ax=a, by=b;
			while(!(ax==0&&by==0)){
			 //It must be noted here that the original data will be changed, so if you do not replace it with a new variable, you will make an error
				int c=ax, d=by;
				v.push_back({ax,by});
				ax=road[c][d][0];
				by=road[c][d][1];
			}
			v.push_back({0,0});
			for(int i=v.size()-1; i>=0; i--){
				printf("(%d, %d)\n", v[i].first, v[i].second);
			}
			return ;
		}
		for(int i=0; i<4; i++){
			int tx=a+dir[i][0], ty=b+dir[i][1];
			if(tx>=0&&tx<=4&&ty>=0&&ty<=4&&mp[tx][ty]==0&&!vis[tx][ty]){
				q.push({tx,ty});
				vis[tx][ty]=1;
				road[tx][ty][0]=a;
				road[tx][ty][1]=b;
			}
		}
	}
}
int main(){
	for(int i=0; i<5; i++)
		for(int j=0; j<5; j++)
			cin >> mp[i][j];
	bfs(0,0);
	return 0;
}

E-Find The Multiple
Title Link
Idea:
For a decimal number consisting of 0 and 1, there are no more than 2 operations:
1,x10
2,x10+1
We can implement it with the help of queue. Note that x must be the first element of the team!!!!

#include <iostream>
#include <stdio.h>
#include <queue>
using namespace std;
typedef long long ll;
queue <ll> q;
int n;
void bfs(ll x){
	while(!q.empty()) q.pop();
	q.push(x);
	while(!q.empty()){
		ll y=q.front();
		q.pop();
		if(y%n==0){
			printf("%lld\n",y);
			return;
		}
		q.push(y*10);
		q.push(y*10+1);
	}
}
int main(){
	while(cin >> n && n!=0){
		bfs(1);
	}
	return 0;
}

F-Fire!
Title Link
Idea:
1. Fire is chasing JOE, so whether JOE will be burned by fire depends on whether the time when JOE reaches a point is less than the time when fire reaches this point. Therefore, it can be found that this is a priority problem, so BFS is used (BFS is used for general maze problems).
2. Two BFS are carried out at the same time. We should consider priority and fire chasing people. Therefore, fire BFS is carried out first, and then JOE BFS.
3. Pay attention to the conditions of each BFS, and pay attention to more than one fire source!!!!
4. The condition for escape is to reach the boundary

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int maxn = 1005;
char mp[maxn][maxn];
int dir[4][2]={-1,0,1,0,0,-1,0,1};
int vis[maxn][maxn]; //Record the minimum time from JOE's starting point to that point
int fire[maxn][maxn];//Record the time when the fire reaches the point
int t, r, c;
int sx, sy;//Initial position of JOE
queue <pii> f;
queue <pii> q;
void BfsFire(){
	while(!f.empty()) f.pop();//Remember to play it clean
	memset(fire,-1,sizeof(fire));
	for(int i=1; i<=r; i++){
		for(int j=1; j<=c; j++){
			if(mp[i][j]=='F'){//Multiple fire sources
				f.push({i,j});
				fire[i][j]=0;
			}
		}
	}
	while(!f.empty()){
		int x=f.front().first;
		int y=f.front().second;
		f.pop();
		for(int i=0; i<4; i++){
			int tx=x+dir[i][0], ty=y+dir[i][1];
			//Note the condition that fire is equivalent to the usual vis array
			if(tx>=1&&tx<=r&&ty>=1&&ty<=c&&mp[tx][ty]!='#'&&fire[tx][ty]==-1){
				fire[tx][ty]=fire[x][y]+1;
				f.push({tx,ty});
			}
		}
	}
}
int MainBfs(int sx, int sy){
	while(!q.empty()) q.pop();
	memset(vis,-1,sizeof(vis));
	vis[sx][sy]=0;
	q.push({sx,sy});
	while(!q.empty()){
		int x=q.front().first, y=q.front().second;
		q.pop();
		if(x==1||y==1||x==r||y==c) return vis[x][y]+1;
		for(int i=0; i<4; i++){
			int tx=x+dir[i][0], ty=y+dir[i][1];
			/*Note the conditions here
			(vis[x][y]+1<fire[tx][ty]||fire[tx][ty]==-1)
			This condition is the worst, because it is possible that the place where the fire cannot go is because it is # surrounded
			And J can just walk there*/
			if(tx>=1&&tx<=r&&ty>=1&&ty<=c&&vis[tx][ty]==-1&&(vis[x][y]+1<fire[tx][ty]||fire[tx][ty]==-1)&&mp[tx][ty]!='#'){
				q.push({tx,ty});
				vis[tx][ty]=vis[x][y]+1;
			}
		}
	}
	return -1;
}
int main(){
	cin >> t;
	while(t--){
		cin >> r >> c;
		for(int i=1; i<=r; i++){
			for(int j=1; j<=c; j++){
				cin >> mp[i][j];
				if(mp[i][j]=='J') sx=i,sy=j;
			}
		}
		BfsFire();
		int res=MainBfs(sx,sy);
		if(res!=-1) printf("%d\n",res);
		else puts("IMPOSSIBLE");
	}
	return 0;
}

G-very cola
Idea:
First, you must understand two points:
1. When the sum of coke is odd, it is impossible to divide equally.
2. We can regard the final result as that the coke bottle itself is equal to the coke in the larger of the two cups (which can be proved by ourselves).
2. Secondly, find the least number of inversions, then BFS must be used, which can be divided into six cases:
s->x
s->y
x->y
y->x
y->s
x->s
BFS can be used for specific conditions respectively, and attention shall be paid to two situations: full filling and full filling.
3. For tag arrays, we don't need to open three dimensions, but we can use two dimensions directly.

#include <bits/stdc++.h>
#define MAX INF
using namespace std;
typedef long long ll;
const int maxn = 2e2+10;
int n, m, l, g; 
int vis[maxn][maxn];
struct node{
	int s, x, y;
	int step;
}; //Store the quantity of coke in 3 cups and the number of times currently poured
node u, t, k;
int bfs(){
	queue <node> q;//Open it inside because the queue needs to be reset
	k.s=l, k.x=0, k.y=0, k.step=0;
	q.push(k);
	vis[k.s][k.x]=1;
	while(!q.empty()){
		u=q.front();
		q.pop();
		if(u.s==l/2&&u.x==l/2) return u.step;//End flag
		for(int i=0; i<6; i++){
			if(i==0){//s->x
				if(u.s+u.x>m){ //Full condition
					t.x=m;
					t.s=u.s-(m-u.x);
				}
				else{  //Under full condition
					t.x=u.s+u.x;
					t.s=0;
				}
				t.y=u.y;
			}
			if(i==1){//s->y
				if(u.s+u.y>n){
					t.y=n;
					t.s=u.s-(n-u.y);
				}
				else{
					t.y=u.s+u.y;
					t.s=0;
				}
				t.x=u.x;
			}
			if(i==2){//x->y
				if(u.x+u.y>n){
					t.y=n;
					t.x=u.x-(n-u.y);
				}
				else{
					t.y=u.x+u.y;
					t.x=0;
				}
				t.s=u.s;
			}
			if(i==3){//y->x
				if(u.x+u.y>m){
					t.x=m;
					t.y=u.y-(m-u.x);
				}
				else{
					t.x=u.x+u.y;
					t.y=0;
				}
				t.s=u.s;
			}
			if(i==4){//y->s
				t.y=0;
				t.x=u.x;
				t.s=u.s+u.y;
			}
			if(i==5){//x->s
				t.x=0;
				t.y=u.y;
				t.s=u.s+u.x;
			}
			if(vis[t.s][t.x]) continue;
			t.step=u.step+1;
			vis[t.s][t.x]=1;
			q.push(t);
		}
	}
	return 0; //Be sure to + up, because this is the output answer
}
int main(){
	cin >> g;
	while(g--){
		cin >> l >> m >> n;
		if(l%2){
			printf("NO\n");
			continue;
		}
		memset(vis,0,sizeof(vis));
		if(m<n) swap(m,n);
		int res=bfs();
		if(res) printf("%d\n",res);
		else printf("NO\n");
	}
	return 0;
}

H-Find a way
Title Link
Idea: two people arrive at the same KFC in the shortest time. There is no doubt that the word "shortest" tells us to use BFS, so we can perform BFs of the whole picture for two people ('#' is not feasible), then record the steps when two people arrive at KFC with disa and disc arrays, and finally find the shortest steps.

#include <bits/stdc++.h>
#define MAX 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e2+10;
int n,m,ax,ay,bx,by;
int vis[maxn][maxn];
char mp[maxn][maxn];
int disa[maxn][maxn];
int disb[maxn][maxn];
int dir[4][2]={-1,0,1,0,0,-1,0,1};
struct node{
	int x,y;
	int sum; //Current steps
}a,b,c,d;
void bfs(int ax, int ay, int bx, int by){
	queue <node> q1;
	queue <node> q2;
	memset(disa,0,sizeof(disa));
	memset(disb,0,sizeof(disb));
	memset(vis,0,sizeof(vis));
	a.x=ax, a.y=ay, a.sum=0;
	b.x=bx, b.y=by, b.sum=0;
	q1.push(a), q2.push(b);
	while(!q1.empty()){
		c=q1.front();
		q1.pop();
		if(mp[c.x][c.y]=='@') disa[c.x][c.y]=c.sum;
		for(int i=0; i<4; i++){
			d.x=c.x+dir[i][0], d.y=c.y+dir[i][1];
			if(d.x>=0&&d.x<n&&d.y>=0&&d.y<m&&mp[d.x][d.y]!='#'&&!vis[d.x][d.y]){
				d.sum=c.sum+1;
				q1.push(d);
				vis[d.x][d.y]=1;
			}
		}
	}
	memset(vis,0,sizeof(vis));//Be sure to reset
	while(!q2.empty()){
		c=q2.front();
		q2.pop();
		if(mp[c.x][c.y]=='@') disb[c.x][c.y]=c.sum;
		for(int i=0; i<4; i++){
			d.x=c.x+dir[i][0], d.y=c.y+dir[i][1];
			if(d.x>=0&&d.x<n&&d.y>=0&&d.y<m&&mp[d.x][d.y]!='#'&&!vis[d.x][d.y]){
				d.sum=c.sum+1;
				q2.push(d);
				vis[d.x][d.y]=1;
			}
		}
	}
}
int main(){
	while(cin>>n>>m){
		for(int i=0; i<n; i++){
			for(int j=0; j<m; j++){
				cin >> mp[i][j];
				if(mp[i][j]=='Y') ax=i,ay=j;
				if(mp[i][j]=='M') bx=i,by=j;
			}
		}
		bfs(ax,ay,bx,by);
		int ans=MAX;
		for(int i=0; i<n; i++){
			for(int j=0; j<m; j++){
				if(disa[i][j]!=0&&disb[i][j]!=0){
					if(ans>disa[i][j]+disb[i][j]) ans=disa[i][j]+disb[i][j];
				}
			}
		}
		printf("%d\n",ans*11);
	}
	return 0;
}

In fact, you can also use BFS twice without writing so difficult.

I-Pots
Title Link
Idea: first, find the least number of operations, then it must be bfs;
It is found that there are 6 operations in each round, which is very similar to that of question G;
! Difficulty: finally, to output the operation steps, that is, to record the operation steps, we can define a structure array to record the volume of water in the current 2 cups, the number of operation steps and the operation mode. At the same time, whether the number of operation steps = = 0 can be used as a common vis array to judge whether bfs has passed. Then find the root of the structure array in dfs, and finally output one by one.

#include <iostream>
#include <queue>
#include <stdio.h>
#include <cstring>
using namespace std;
const int maxn = 110;
int a, b, c;
char s[10][10]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
struct node{
	int sum1, sum2, op, step;
}v[maxn][maxn];//1 medium volume, 2 volume, operation mode, number of operation steps
struct nodex{
	int x, y;
}m,n;//This is used to join the team for bfs. It stores the volume in the current 1 and 2 cups
void dfs(int x, int y){
	if(x==0&&y==0) return;
	dfs(v[x][y].sum1,v[x][y].sum2);
	printf("%s\n",s[v[x][y].op]);
}
void bfs(){
	m.x=0, m.y=0;
	v[0][0].step=1;
	queue <nodex> q;
	q.push(m);
	while(!q.empty()){
		n=q.front();
		q.pop();
		if(n.x==c||n.y==c){
			printf("%d\n",v[n.x][n.y].step-1);
			dfs(n.x,n.y);
			return;
		}
		for(int i=1; i<=6; i++){
			m=n;
			if(i==1) m.x=a;
			else if(i==2) m.y=b;
			else if(i==3) m.x=0;
			else if(i==4) m.y=0;
			//For the following steps, be sure to pay attention to the sequence
			else if(i==5){
				if(m.x+m.y<=b){
				//The two steps here must not be reversed!!!!! (I always WA)
					m.y=m.x+m.y;
					m.x=0;
				}
				else{
					m.x-=(b-m.y);
					m.y=b;
				}
			}
			else{
				if(m.x+m.y<=a){
					m.x=m.x+m.y;
					m.y=0;
				}
				else{
					m.y-=(a-m.x);
					m.x=a;
				}
			}
			if(v[m.x][m.y].step==0){
				v[m.x][m.y].sum1=n.x;
				v[m.x][m.y].sum2=n.y;
				v[m.x][m.y].op=i-1;
				v[m.x][m.y].step=v[n.x][n.y].step+1;
				q.push(m);
			}
		}
	}
	printf("impossible\n");
}
int main(){
	cin >> a >> b >> c;
	bfs();
	return 0;
}

Topics: C Algorithm data structure