蓝桥杯 历届试题 九宫重排 双向dfs

一开始用的单向dfs 毫无意外超时了 只得了60分
后面搜了一下,发现要用双向dfs ,试了一下终于过了
在这里插入图片描述

我的思路:
①状态转换还是用数组进行四个方向的操作
     int dx[4]={0, -1, 0, 1}, dy[4]={-1, 0, 1, 0};

②用map<string, int> ma记录每个string表示的状态是否被访问过 和 ms记录到达该状态的步骤数
     map<string, int> ma, ms;
//ma中0值表示该状态没出现过, 1值表示从初态出发到达的状态, 2值表示从终态出发的状态
//ms的值表示到达每个状态所需的步数

③双向dfs:
   分别从初态和终态出发,初态ma[start]=1, 终态ma[end]=2
由当前状态current到下一状态next:

  Ⅰ.该状态未被访问过(即ma[next]==0)
ma[next] = ma[current]; //即由初态到达的每一状态ma的值都等于1, 由终态出发的每一状态的值都等于2

  Ⅱ. 若该状态已被访问过(即ma[next]==1或者ma[next]==2)
判断ma[current]+ma[next]是否等于3,若等于三,则证明这两个是分别从初态和终态出发到达的中间状态,只要把它俩的步骤数加起来再加1,这个1是从current状态再next状态的步骤数,就是答案了;


我的代码:

#include<bits/stdc++.h>
using namespace std;
int dx[4]={0, -1, 0, 1}, dy[4]={-1, 0, 1, 0};
int a[3][3], b[3][3], sx, sy, ex, ey;

struct Node{
	int arr[3][3];	//数组记录每个九宫格状态 
	int x, y;	//x, y记录每个状态.的坐标 
	string str;	//九宫格的字符串表示 
} node[100000];

map<string, int> ma, ms;//ma中0值表示该状态没出现过, 1值表示从初态出发到达的状态, 2值表示从终态出发的状态
						//ms的值表示到达每个状态所需的步数 

//将数组转化为字符串函数 
string toMap(int a[3][3]){
	string ans="";
	for(int i=0 ;i<3; i++){
		for(int j=0; j<3; j++){
			ans += a[i][j]+'0';
		}
	}
	return ans;
}

//用数组模拟队列进行双向dfs 
int bfs(Node nd, Node nd2){
	int head = 0, tail = 0;
	node[tail++] = nd;
	node[tail] = nd2;
	ma[nd.str] = 1;
	ma[nd2.str] = 2;
	
	while(head<=tail){
		Node t = node[head];
		
		for(int i=0; i<4; i++){
			int nx = t.x + dx[i], ny = t.y + dy[i];
			if(nx>=0&&nx<3&&ny>=0&&ny<3){
				Node tmp;
				memcpy(tmp.arr, t.arr, sizeof(t.arr));
				tmp.arr[t.x][t.y] = tmp.arr[nx][ny];
				tmp.arr[nx][ny] = 0;
				tmp.str = toMap(tmp.arr);
				
				if(!ma[tmp.str]){
					ma[tmp.str] = ma[t.str];
					ms[tmp.str] = ms[t.str] + 1;
					tmp.x = nx, tmp.y = ny;
					node[++tail] = tmp;
				}else{
					if(ma[tmp.str]+ma[t.str]==3)	//两者相加等于3代表一个是由初态出发,一个是由终态出发,到达了中间状态 
						return ms[tmp.str]+ms[t.str]+1;	//所以就等于两个状态的步骤数相加再+1 
				}
			}
			
		}
		head++;
	}
	return -1;
}

int main(){
	char c;
	
	//输入初态数组 
	for(int i=0; i<3; i++){
		for(int j=0; j<3; j++){
			cin>>c;
			if(c=='.'){
				a[i][j] = 0;
				sx = i, sy = j;
			}else{
				a[i][j] = c - '0';
			}
		}
	}

	//输入终态数组 
	for(int i=0; i<3; i++){
		for(int j=0; j<3; j++){
			cin>>c;
			if(c=='.'){
				b[i][j] = 0;
				ex = i, ey = j;
			}else{
				b[i][j] = c - '0';
			}
		}
	}
	
	Node t;
	memcpy(t.arr, a, sizeof(a));
	t.x = sx, t.y = sy;
	ms[t.str]  = 0;
	t.str = toMap(t.arr);

	Node t2;
	memcpy(t2.arr, b, sizeof(b));
	t2.x = ex, t2.y = ey;
	t2.str = toMap(t2.arr);

	cout<<bfs(t, t2)<<endl;
	return 0;
} 
发布了46 篇原创文章 · 获赞 1 · 访问量 2403

猜你喜欢

转载自blog.csdn.net/weixin_43708069/article/details/104449161