[解题报告]训练日记2:搜索专题

题目链接(除去E题)

训练的时候没有E题 以下题解按照本链接题号

为什么不放训练链接?因为有密码啊。

有些题基本一个套路,但是有的题还是好废脑子和码力的

细节处理的并不是多么好…

A

dfs搜索每一行每一列,用一维vis数组判断是否访问过这一列

因为我们是一行一行的搜索的,所以一行肯定会有一个,不用二维数组

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n , k , cnt , vis[10];
char map[10][10];

void dfs(int x , int y) {
    
    
	if(y==0) {
    
    
		cnt++;
		return ;
	}
	for(int j=x; j<=n; j++)
		for(int i=1; i<=n; i++) {
    
    
			if(vis[i]==1||map[j][i]=='.')
				continue;
			vis[i] = 1;
			dfs(j+1 , y-1);
			vis[i] = 0;
		}
}

int main() {
    
    
//	freopen("data.txt","r",stdin);
	while(1) {
    
    
		scanf("%d%d",&n,&k);
		if(n==-1&&k==-1)
			break;
		cnt = 0;
		memset(vis , 0 , sizeof(vis));
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++)
				cin>>map[i][j];
		dfs(1 , k);
		printf("%d\n",cnt);
	}
	return 0;
} 

B

三维bfs 与平常做的没太大区别 就是多加一个变量

判断的时候多加一个z轴就好

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

struct Node {
    
    
	int x , y , z , t;
};
int L , R , C , sx , sy , sz , vis[35][35][35];
char map[35][35][35];

int check(int x , int y , int z) {
    
    
	if(x>=1&&y>=1&&z>=1&&x<=R&&y<=C&&z<=L&&vis[x][y][z]==0&&map[z][x][y]!='#')
		return 0;
	return 1;
}

void bfs() {
    
    
	queue<Node>q;
	Node x;
	x.x = sx;
	x.y = sy;
	x.z = sz;
	x.t = 0;
	vis[x.x][x.y][x.z] = 1;
	q.push(x);
	while(!q.empty()) {
    
    
		Node u = q.front() , v;
		u.t++;
		q.pop();
		if(map[u.z][u.x][u.y]=='E') {
    
    
			printf("Escaped in %d minute(s).\n" , u.t-1);
			return ;
		}
		if(check(u.x+1 , u.y , u.z)==0) {
    
    		
			v = u;
			v.x++;
			q.push(v);
			vis[v.x][v.y][v.z] = 1;			
		}
		if(check(u.x-1 , u.y , u.z)==0) {
    
    		
			v = u;	
			v.x--;
			q.push(v);
			vis[v.x][v.y][v.z] = 1;
		}
		if(check(u.x , u.y+1 , u.z)==0) {
    
    		
			v = u;
			v.y++;
			q.push(v);
			vis[v.x][v.y][v.z] = 1;			
		}
		if(check(u.x , u.y-1 , u.z)==0) {
    
    		
			v = u;
			v.y--;
			q.push(v);
			vis[v.x][v.y][v.z] = 1;			
		}
		if(check(u.x , u.y , u.z+1)==0) {
    
    		
			v = u;
			v.z++;
			q.push(v);
			vis[v.x][v.y][v.z] = 1;			
		}
		if(check(u.x , u.y , u.z-1)==0) {
    
    		
			v = u;
			v.z--;
			q.push(v);
			vis[v.x][v.y][v.z] = 1;			
		}
	}
	printf("Trapped!\n");
}

int main() {
    
    
//	freopen("data.txt","r",stdin);
	while(1) {
    
    
		scanf("%d%d%d",&L,&R,&C);
		if(L==0&&R==0&&C==0)
			break;
		memset(vis , 0 , sizeof(vis));
		for(int i=1; i<=L; i++)
			for(int j=1; j<=R; j++)
				for(int k=1; k<=C; k++) {
    
    
					cin>>map[i][j][k];
					if(map[i][j][k]=='S') {
    
    
						sz = i;
						sx = j;
						sy = k;
					}
				}
		bfs();
	}
	return 0;
}

C

裸的bfs 三种操作对应入队

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

struct Node {
    
    
	int x , t;
};
queue<Node>q;
int n , k , vis[100005];

int check(Node x) {
    
    
	if(x.x>=0&&x.x<=100000&&vis[x.x]==0)
		return 1;
	return 0;
}

void bfs() {
    
    
	Node x;
	x.x = n;
	x.t = 0;
	q.push(x);
	vis[n] = 1;
	while(!q.empty()) {
    
    
		Node u = q.front() , v;
		q.pop();
		if(u.x==k) {
    
    
			printf("%d",u.t);
			return ;
		}
		v = u; v.t++;
		v.x++;
		if(check(v)==1) {
    
    
			q.push(v);
			vis[v.x] = 1;
		}
		v = u; v.t++;
		v.x--;
		if(check(v)==1) {
    
    
			q.push(v);
			vis[v.x] = 1;
		}
		v = u; v.t++;
		v.x = v.x*2;
		if(check(v)==1) {
    
    
			q.push(v);
			vis[v.x] = 1;
		}
	}
}

int main() {
    
    
//	freopen("data.txt","r",stdin);
	scanf("%d%d",&n,&k);
	bfs();
	return 0;
} 

D

没A , 待更

F

还是个裸题吧 只是判断的条件不一样

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;

struct Node {
    
    
	int x , t;
};
int n , a , b , vis[10005] , flag;

int jud(int x) {
    
    
	double xx = (double)x;
	for(int i=2; i<=sqrt(xx); i++)
		if(x%i==0)
			return 0;
	return 1;
}

void bfs() {
    
    
	queue<Node>q;
	Node x;
	x.x = a;
	x.t = 0;
	vis[x.x] = 1;
	q.push(x);
	while(!q.empty()) {
    
    
		Node u = q.front() , v;
		q.pop();
		if(u.x==b) {
    
    
			flag = 1;
			printf("%d\n",u.t);
			return ;
		}
		for(int i=1; i<=9; i++) {
    
    
			if(i==u.x/1000)
				continue;
			int num = i*1000 + u.x%1000;
		//	cout<<num<<endl;
			if(jud(num)==1&&vis[num]==0) {
    
    
				v.t = u.t + 1;
				v.x = num;
				q.push(v);
				vis[v.x] = 1;
			}
		}
		for(int i=0; i<=9; i++) {
    
    
			int m = u.x/100-(u.x/1000)*10;
			if(i==m)
				continue;
			int num = u.x-m*100+i*100;
			//	cout<<num<<endl;
			if(jud(num)==1&&vis[num]==0) {
    
    
				v.t = u.t + 1;
				v.x = num;
				q.push(v);
				vis[v.x] = 1;				
			}
		}
		for(int i=0; i<=9; i++) {
    
    
			int m = u.x/10-(u.x/100)*10;
			if(i==m)
				continue;
			int num = u.x-m*10+i*10;
			//	cout<<num<<endl;
			if(jud(num)==1&&vis[num]==0) {
    
    
				v.t = u.t + 1;
				v.x = num;
				q.push(v);
				vis[v.x] = 1;
			}
		}
		for(int i=1; i<=9; i+=2) {
    
    
			int m = u.x%10;
			if(i==m)
				continue;
			int num = u.x-m+i;
		//		cout<<num<<endl;
			if(jud(num)==1&&vis[num]==0) {
    
    
				v.t = u.t + 1;
				v.x = num;
				q.push(v);
				vis[v.x] = 1;
			}
		}
	}
}

int main() {
    
    
	//freopen("data.txt","r",stdin);
	scanf("%d",&n);
//	cout<<jud(n);
	for(int i=1; i<=n; i++) {
    
    
		scanf("%d%d",&a,&b);
		flag = 0;
		memset(vis , 0 , sizeof(vis));
		bfs();
		if(flag==0)
			printf("Impossible\n");
	}
	return 0;
}

G

map代替数组来实现vis的功能

一直搜下去 dfs 啊

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<map>
using namespace std;

string A , B , C;
int T , n , len , ff , tt;
map<string , int>vis;

void dfs(string S1 , string S2 , int t) {
    
    
	if(ff)
		return ; 
	int flag = 1 , top = 0;
	string S3 = "";
	while(1) {
    
    
		if(top==len)
			break;
		if(flag==1) {
    
    
			S3 += S2[top];
			flag = 2;
		}
		if(flag==2) {
    
    
			S3 += S1[top];
			flag = 1;
		}
		top++;
	}
//	cout<<S3<<endl;
	if(S3==C) {
    
    
		printf("%d %d\n",tt,t);
		return ;
	}
	if(vis[S3]) {
    
    
		ff = 1;
		return ;
	}
	vis[S3] = 1;
//	cout<<S3.substr(0,len)<<" "<<S3.substr(len,len);
	dfs(S3.substr(0,len) , S3.substr(len,len) , t+1);
//	cout<<S3<<endl;
}

int main() {
    
    
	//freopen("data.txt","r",stdin);
	tt = 0;
	scanf("%d",&T);
	while(T--) {
    
    
		tt++;
		vis.clear();
		scanf("%d",&len);
		ff = 0;
		cin>>A>>B>>C;
		dfs(A , B , 1);
		if(ff)
			printf("%d -1\n",tt);
	}
	return 0;
} 

H

比较好(恶心)的搜索题

就是两个罐去实现六个操作而已 bfs将每个操作压进队列

然后一个裸的bfs就能求出操作数(第一问)

恶心就恶心在 这题有第二问 要问每个操作

所以在bfs的时候记录一下上一步的操作

这样结束之后只需要在结尾的状态dfs回去 边深搜输出即解决该题

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<map>
using namespace std;

struct Node {
    
    
	int a , b , t;
};
queue<Node>q;
struct Pre {
    
    
	int a , b , f;
};
Pre pre[105][105];
int A , B , C , vis[105][105] , sx , sy;

void pour1(int &a , int &b) {
    
    
	if(a>=B-b) {
    
    
		a = a-(B-b);
		b = B;
	} else {
    
    
		b = b + a;
		a = 0;
	}
}

void pour2(int &b , int &a) {
    
    
	if(b>=A-a) {
    
    
		b = b-(A-a);
		a = A;
	} else {
    
    
		a = a + b;
		b = 0;
	}
}

void bfs() {
    
    
	Node x;
	x.a = 0;
	x.b = 0;
	x.t = 0;
	vis[0][0] = 1;
	q.push(x);
	while(!q.empty()) {
    
    
		Node u = q.front() , v;
		q.pop();
		if(u.a==C||u.b==C) {
    
    
			sx = u.a;
			sy = u.b;
			printf("%d\n",u.t);
			return ;
		}
		v = u;
		v.t++;
		v.a = A;
		if(!vis[v.a][v.b]) {
    
    
			vis[v.a][v.b] = 1;
			pre[v.a][v.b].a = u.a;
			pre[v.a][v.b].b = u.b;
			pre[v.a][v.b].f = 1;
			q.push(v);
		}
		v = u;
		v.t++;
		v.b = B;
		if(!vis[v.a][v.b]) {
    
    
			vis[v.a][v.b] = 1;
			pre[v.a][v.b].a = u.a;
			pre[v.a][v.b].b = u.b;
			pre[v.a][v.b].f = 2;
			q.push(v);
		}
		v = u;
		v.t++;
		pour1(v.a , v.b);
		if(!vis[v.a][v.b]) {
    
    
			vis[v.a][v.b] = 1;
			pre[v.a][v.b].a = u.a;
			pre[v.a][v.b].b = u.b;
			pre[v.a][v.b].f = 3;
			q.push(v);
		}	
		v = u;
		v.t++;
		pour2(v.b , v.a);
		if(!vis[v.a][v.b]) {
    
    
			vis[v.a][v.b] = 1;
			pre[v.a][v.b].a = u.a;
			pre[v.a][v.b].b = u.b;
			pre[v.a][v.b].f = 4;
			q.push(v);
		}
		v = u;
		v.t++;
		v.a = 0;
		if(!vis[v.a][v.b]) {
    
    
			vis[v.a][v.b] = 1;
			pre[v.a][v.b].a = u.a;
			pre[v.a][v.b].b = u.b;
			pre[v.a][v.b].f = 5;
			q.push(v);
		}
		v = u;
		v.t++;
		v.b = 0;
		if(!vis[v.a][v.b]) {
    
    
			vis[v.a][v.b] = 1;
			pre[v.a][v.b].a = u.a;
			pre[v.a][v.b].b = u.b;
			pre[v.a][v.b].f = 6;
			q.push(v);
		}		
	}
}

void dfs(int a , int b) {
    
    
	if(a==0&&b==0)
		return ;
	dfs(pre[a][b].a , pre[a][b].b);
	if(pre[a][b].f==1)
		printf("FILL(1)\n");
	if(pre[a][b].f==2)
		printf("FILL(2)\n");
	if(pre[a][b].f==3)
		printf("POUR(1,2)\n");
	if(pre[a][b].f==4)
		printf("POUR(2,1)\n");
	if(pre[a][b].f==5)
		printf("DROP(1)\n");	
	if(pre[a][b].f==6)
		printf("DROP(2)\n");
}

int main() {
    
    
	//freopen("data.txt","r",stdin);
	scanf("%d%d%d",&A,&B,&C);
	bfs();
	if(sx==0&&sy==0) {
    
    
		printf("impossible");
		return 0;
	}
	dfs(sx , sy);
	//cout<<sx<<" "<<sy;
	return 0;
}

I

这题我提交了好多次都T了

我还以为是这道题卡常特别厉害呢 结果…

是一种特殊情况:只有一个#的情况没考虑到!

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

#define INF 2147483647
struct Node {
    
    
	int x , y , t;
};
vector<Node>z;
char map[15][15];
int T , m , n , dx[10] , dy[10] , vis[15][15] , minn , flag , maxx , cas , sz;

void read(int &x)
{
    
    
    char c = getchar(); x = 0;
    while(c < '0' || c > '9') c = getchar();
    while(c <= '9' && c >= '0') x = x*10+c-48, c = getchar();
}

void init() {
    
    
	z.clear();
	cas++;
	minn = INF;
}

int jud(int x , int y) {
    
    
	if(x>=1&&x<=n&&y>=1&&y<=m&&vis[x][y]==0&&map[x][y]=='#')
		return 1;
	return 0;
}

void bfs(int x1 , int y1 , int x2 , int y2) {
    
    
	Node s1 , s2;
	s1.x = x1; s1.y = y1; s1.t = 0;
	s2.x = x2; s2.y = y2; s2.t = 0;
	vis[x1][y1] = 1;
	vis[x2][y2] = 1;
	queue<Node>q;
	if(s1.x==s2.x&&s1.y==s2.y)
		q.push(s1);
	else {
    
    
		q.push(s1);
		q.push(s2);
	}
	while(!q.empty()) {
    
    
		Node u = q.front();
		q.pop();
		for(int i=1; i<=4; i++) {
    
    
			Node v;
			int sx = u.x+dx[i] , sy = u.y+dy[i];
			if(jud(sx , sy)) {
    
    
				vis[sx][sy] = vis[u.x][u.y] + 1;
				v.x = sx;
				v.y = sy;
				v.t = u.t + 1;
				q.push(v);
			}
		}
	}
}

void check() {
    
    
	maxx = -1;
	for(int i=0; i<sz; i++) {
    
    
		if(vis[z[i].x][z[i].y]==0) {
    
    
			flag = 1;
			return ;
		}
		maxx = max(maxx , vis[z[i].x][z[i].y]-1);		
	}
}

int main() {
    
    
	//freopen("data.txt","r",stdin);
	dx[1] = -1; dy[1] = 0;
	dx[2] = 1; dy[2] = 0;
	dx[3] = 0; dy[3] = -1;
	dx[4] = 0; dy[4] = 1;
	read(T);
	while(T--) {
    
    
		init();
		read(n); read(m);
		for(int i=1; i<=n; i++)
			for(int j=1; j<=m; j++) {
    
    
				cin>>map[i][j];
				if(map[i][j]=='#') {
    
    
					Node x;
					x.x = i;
					x.y = j;
					z.push_back(x);
				}
			} 
		sz = z.size();
		if(sz==1) {
    
    
			printf("Case %d: 0\n",cas);
			continue;
		}
		for(int i=0; i<sz; i++)
			for(int j=0; j<sz; j++) {
    
    
				memset(vis , 0 , sizeof(vis));
				flag = 0;
				bfs(z[i].x , z[i].y , z[j].x , z[j].y);
				check();
				if(flag==0)
					minn = min(minn , maxx);					
			}
		if(minn==INF)
			printf("Case %d: -1\n",cas);
		else
			printf("Case %d: %d\n",cas,minn);
	}
	return 0;
}

J

算是比较巧妙吧

先求几堆火到各个可以到的位置的时间

再求人到各个点的时间 注意:只有人的时间小于火到这的时间才能入队

为什么没有取最小值?因为跑过的点都被打上vis标记了 按照bfs搜索的过程知道前面搜到的是距离(时间)短的那个

所以本题就是先跑fire的bfs,再跑人的bfs 入对的条件多了判断时间

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

#define INF 2147483647
struct Node {
    
    
	int x , y , t;
};
Node s;
char map[1005][1005]; 
int T , n , m , sz , mp , vis[1005][1005] , dx[10] , dy[10] , dis[1005][1005] , ans;
vector<Node>edge;
queue<Node>fire;

void init() {
    
    
	ans = INF;
	dx[1] = -1; dy[1] = 0;
	dx[2] = 1; dy[2] = 0;
	dx[3] = 0; dy[3] = -1;
	dx[4] = 0; dy[4] = 1;
	memset(vis , 0 , sizeof(vis));
}

int jud(int x , int y) {
    
    
	if(x>=1&&x<=n&&y>=1&&y<=m&&vis[x][y]==0&&map[x][y]!='#')
		return 1;
	return 0;
}

void _bfs() {
    
    
	memset(dis , 0x3f , sizeof(dis));
	while(!fire.empty()) {
    
    
		Node u = fire.front() , v;
		fire.pop();
		dis[u.x][u.y] = u.t;
		for(int i=1; i<=4; i++) {
    
    
			int mx = u.x+dx[i] , my = u.y+dy[i];
			if(jud(mx , my)) {
    
    
				vis[mx][my] = 1;
				v.x = mx;
				v.y = my;
				v.t = u.t + 1;
				fire.push(v);
			}
		}
	}
}

void bfs() {
    
    
	queue<Node>q;
	q.push(s);
	_bfs();
	memset(vis , 0 , sizeof(vis));
	vis[s.x][s.y] = 1;
	while(!q.empty()) {
    
    
		Node u = q.front() , v;
		q.pop();
		if(u.x==n||u.y==m||u.x==1||u.y==1) {
    
    
			ans = u.t + 1;
			return ;
		}
		for(int i=1; i<=4; i++) {
    
    
			int mx = u.x+dx[i] , my = u.y+dy[i];
			if(jud(mx , my)&&map[mx][my]=='.'&&u.t+1<dis[mx][my]) {
    
    
				vis[mx][my] = 1;
				v.x = mx;
				v.y = my;
				v.t = u.t + 1;
				q.push(v);
			}
		}
	}
} 

int main() {
    
    
//	freopen("data.txt","r",stdin);
	scanf("%d",&T);
	while(T--) {
    
    
		init();
		scanf("%d%d",&n,&m);
		for(int i=1; i<=n; i++)
			for(int j=1; j<=m; j++) {
    
    
				cin>>map[i][j];
				if(map[i][j]=='J') {
    
    
					s.x = i;
					s.y = j;
					s.t = 0;
				}
				if(map[i][j]=='F') {
    
    
					Node x;
					x.x = i;
					x.y = j;
					x.t = 0;
					vis[x.x][x.y] = 1;
					fire.push(x);
				}
			}
		bfs();
		if(ans==INF)
			printf("IMPOSSIBLE\n");
		else
			printf("%d\n",ans);
	}
	return 0;
}

K

很像G题 就是bfs搜索+dfs输出答案

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

struct Node {
    
    
	int x , y , t;
};
priority_queue<Node>q;
Node pre[10][10];
int map[10][10] , vis[10][10] , dx[10] , dy[10];

bool operator < (Node a , Node b) {
    
    
	return a.t > b.t;
}

void init() {
    
    
	dx[1] = -1; dy[1] = 0;
	dx[2] = 1; dy[2] = 0;
	dx[3] = 0; dy[3] = -1;
	dx[4] = 0; dy[4] = 1;
}

int jud(int x , int y) {
    
    
	if(x>=0&&x<=4&&y>=0&&y<=4&&vis[x][y]==0&&map[x][y]==0)
		return 1;
	return 0;
}

void bfs() {
    
    
	Node x;
	x.x = 0;
	x.y = 0;
	x.t = 0;
	vis[0][0] = 1;
	q.push(x);
	while(!q.empty()) {
    
    
		Node u = q.top();
		q.pop();
		for(int i=1; i<=4; i++) {
    
    
			int sx = u.x+dx[i] , sy = u.y+dy[i];
			Node v;
			v.x = sx;
			v.y = sy;
			v.t = u.t + 1;	
			if(jud(sx , sy)) {
    
    
				vis[sx][sy] = 1;
				pre[sx][sy].x = u.x;
				pre[sx][sy].y = u.y;
				q.push(v);
			}
		}
	}
}

void dfs(int x , int y) {
    
    
	if(x==0&&y==0)
		return ;
	dfs(pre[x][y].x , pre[x][y].y);
	printf("(%d, %d)\n",x,y);
}

int main() {
    
    
	//freopen("data.txt","r",stdin);
	for(int i=0; i<=4; i++)
		for(int j=0; j<=4; j++)
			scanf("%d",&map[i][j]);
	init();
	bfs();
	printf("(0, 0)\n");
	dfs(4 , 4);
	return 0;
}

L

用每一个@位置开始dfs 记录连通着的个数呗 有8个方向

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

int n , m , dx[10] , dy[10] , ans;
char map[105][105];

void init() {
    
    
	dx[1] = -1; dy[1] = 0;
	dx[2] = 1; dy[2] = 0;
	dx[3] = 0; dy[3] = -1;
	dx[4] = 0; dy[4] = 1;
	dx[5] = -1; dy[5] = -1;
	dx[6] = -1; dy[6] = 1;	
	dx[7] = 1; dy[7] = -1;
	dx[8] = 1; dy[8] = 1;
}

int jud(int x , int y) {
    
    
	if(x>=1&&x<=n&&y>=1&&y<=m&&map[x][y]=='@')
		return 1;
	return 0;
}

void dfs(int x , int y) {
    
    
	map[x][y] = '*';
	for(int i=1; i<=8; i++) {
    
    
		int sx = x+dx[i] , sy = y+dy[i];
		if(jud(sx , sy))
			dfs(sx , sy);
	}
}

int main() {
    
    
	//freopen("data.txt","r",stdin);
	init();
	while(1) {
    
    
		scanf("%d%d",&n,&m);
		if(n==0&&m==0)
			break;
		ans = 0;
		for(int i=1; i<=n; i++)
			for(int j=1; j<=m; j++)
				cin>>map[i][j];
		for(int i=1; i<=n; i++)
			for(int j=1; j<=m; j++)
				if(map[i][j]=='@') {
    
    
					dfs(i , j);	
					ans++;			
				}
		printf("%d\n",ans);
	}
	return 0;
}

M

和G题类似,就是倒水问题

为了让代码简单点 就在结构体里写了数组

或者… 不嫌麻烦可以挨个写开(估计累死)

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

struct Node {
    
    
	int v[5] , t;
};
Node op;
int vis[105][105][105] , V[5] , flag;

void init() {
    
    
	flag = 0;
	memset(vis , 0 , sizeof(vis));
}

Node pour(Node x , int from , int  to) {
    
    
	Node v = x;
	v.t = x.t + 1;
	if(x.v[from]>V[to]-x.v[to]) {
    
    
		v.v[from] = x.v[from] - (V[to] - x.v[to]);
		v.v[to] = V[to];
	} else {
    
    
		v.v[to] = v.v[to] + x.v[from];
		v.v[from] = 0;
	}
	return v;
}

int check(Node x) {
    
    
	if((x.v[1]==0&&x.v[2]==V[1]/2&&x.v[2]==x.v[3])||(x.v[2]==0&&x.v[1]==V[1]/2&&x.v[1]==x.v[3])||(x.v[3]==0&&x.v[1]==V[1]/2&&x.v[1]==x.v[2]))
		return 1;
	return 0;
}

void bfs() {
    
    
	queue<Node>q;
	op.t = 0;
	vis[op.v[1]][op.v[2]][op.v[3]] = 1;
	q.push(op);
	while(!q.empty()) {
    
    
		Node u = q.front() , v;
		q.pop();
		if(check(u)) {
    
    
			printf("%d\n",u.t);
			flag = 1;
			return ;
		}
		for(int i=1; i<=3; i++)
			for(int j=1; j<=3; j++) {
    
    
				if(i==j)
					continue;
				if(u.v[i]==0)
					continue;
				v = pour(u , i , j);
				if(!vis[v.v[1]][v.v[2]][v.v[3]]) {
    
    
					vis[v.v[1]][v.v[2]][v.v[3]] = 1;
					q.push(v);
				}
			}
	}
}

int main() {
    
    
//	freopen("data.txt","r",stdin);
	while(1) {
    
    
		for(int i=1; i<=3; i++)
			scanf("%d",&V[i]);
		op.v[1] = V[1];
		op.v[2] = 0;
		op.v[3] = 0;
		if(V[1]==0&&V[2]==0&&V[3]==0)
				break;
		if(V[1]%2==1||V[1]!=V[2]+V[3]) {
    
    
			printf("NO\n");
			continue;
		}
		init();
		bfs();
		if(!flag)
			printf("NO\n");
	}
	return 0;
}

N

其实就是bfs求两个人到每个点的距离,用动态数组存下每个KFC的位置

然后枚举每个KFC 求一个距离最小值乘11即可

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

#define INF 2147483647
struct Node {
    
    
	int x , y , t;
};
queue<Node>q;
vector<Node>mp;
int n , m , sx , sy , tx , ty , dx[10] , dy[10] , vis[205][205] , dis[3][205][205] , sz , minn;
char map[205][205];

void init() {
    
    
	dx[1] = -1; dy[1] = 0;
	dx[2] = 1; dy[2] = 0;
	dx[3] = 0; dy[3] = -1;
	dx[4] = 0; dy[4] = 1;
}

int jud(int x , int y) {
    
    
	if(x>=1&&x<=n&&y>=1&&y<=m&&map[x][y]!='#'&&vis[x][y]==0)
		return 1;
	return 0;
}

void bfs(int x , int y , int f) {
    
    
	Node xx;
	memset(vis , 0 , sizeof(vis));
	xx.x = x; xx.y = y; xx.t = 0; vis[x][y] = 1;
	q.push(xx);
	while(!q.empty()) {
    
    
		Node u = q.front() , v;
		q.pop();
		if(map[u.x][u.y]=='@')
			dis[f][u.x][u.y] = u.t;
		for(int i=1; i<=4; i++) {
    
    
			int mx = u.x+dx[i] , my = u.y+dy[i];
			if(jud(mx , my)) {
    
    
				vis[mx][my] = 1;
				v.x = mx;
				v.y = my;
				v.t = u.t + 1;
				q.push(v);
			}
		}
	}
}

int main() {
    
    
//	freopen("data.txt","r",stdin);
	init();
	while(scanf("%d%d",&n,&m)!=EOF) {
    
    
		minn = INF;
		memset(dis , 0 , sizeof(dis));
		mp.clear();
		for(int i=1; i<=n; i++)
			for(int j=1; j<=m; j++) {
    
    
				cin>>map[i][j];	
				if(map[i][j]=='Y') {
    
    
					sx = i;
					sy = j;
				}		
				if(map[i][j]=='M') {
    
    
					tx = i;
					ty = j;
				}
				if(map[i][j]=='@') {
    
    
					Node mm;
					mm.x = i;
					mm.y = j;
					mp.push_back(mm);
				}
			}
		sz = mp.size();
		bfs(sx , sy , 1);
		bfs(tx , ty , 2);
		for(int i=0; i<sz; i++) {
    
    
			if(dis[1][mp[i].x][mp[i].y]==0||dis[2][mp[i].x][mp[i].y]==0)
				continue;
			minn = min(minn , dis[1][mp[i].x][mp[i].y] + dis[2][mp[i].x][mp[i].y]);	
		}
		printf("%d\n",minn*11);
	}
	return 0;
}

看了这么多 谁还会看到这呢

搜索的思路还是能回想起来的 就是细节处理不好加上码力比较

肝废了…

猜你喜欢

转载自blog.csdn.net/cls1277/article/details/109680854
今日推荐