88888888y

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
统计
 

题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1451

题目简述:有两个4*4的黑白棋盘,每一个棋子可以与它上下左右的棋子交换

求第一个棋盘最少经过几次变到第二个棋盘

思路:“最少”,毫无疑问,bfs。

这边用队列存储每个分支棋盘以及用最初棋盘做出此分支所用的步数

因此,我们的队列会是一个结构体队列

然后就是去去分支

由于某一个棋子向左向下换位后得到的棋盘已经是这个棋盘的上一个棋盘

所以只需要考虑向下向右换位的即可

然后就是存储

队列里面是不可能存一个数组的

所以我们考虑用二进制的写法来存

而换位就靠异或

上代码

#include<bits/stdc++.h>
using namespace std;
int i,s1,s2;char c;
//由于输入格式的局限性,输入这个棋盘用char 
struct yfwguigdyweiugh{
	int sum,t;
};//sum是当前棋盘,t是用最初棋盘做出此分支所用的步数 
bool v[100000];
int bfs(){
	yfwguigdyweiugh a,b;
	queue<yfwguigdyweiugh> q;
	a.sum=s1;
	a.t=0;
	q.push(a);
	//上文全是初始化 
	while(!q.empty()){//如果还有的搜 
		a=q.front();//把最前面那个分支拿出来 
		q.pop();
		if(a.sum==s2){//棋盘重合了意味着找到了 
			return a.t;//直接回溯 
		}
		int l=a.sum;
		for(int i=15;i>=0;i--){
			b=a;
			int x=(15-i)%4;
			int y=(15-i)/4;
			//找到这个棋子在棋盘中的横纵坐标 
			int z,o=(1<<i);
			if(x<3&&(l&(1<<i))!=(l&(1<<i-1))){//左右能换 
				z=1<<(i-1);
				if(!v[l^o^z]){//就用异或换 
					v[l^o^z]=true;
					b.sum=l^o^z;
					b.t++;
					q.push(b);//存下来 
					b.t--;//记得回溯 
				}
			}
			if(y<3&&(l&(1<<i))!=(l&(1<<i-4))){//上下能换 
				z=1<<(i-4);
				if(!v[l^o^z]){//就用异或换
					v[l^o^z]=true;
					b.sum=l^o^z;
					b.t++;
					q.push(b);//存进来 
					//本次无需回溯 
				}
			}
		}
	}
}
int main(){
	memset(v,false,sizeof(v));
	for(i=15;i>=0;i--){
		cin>>c;
		if(c=='1'){
			s1+=1<<i;
		}
	}
	for(i=15;i>=0;i--){
		cin>>c;
		if(c=='1'){
			s2+=1<<i;
		}
	}
	printf("%d",bfs());
	return 0;
}

总结:做这题需要有强大的知识储备

做不出来的建议重修位运算

posted on   88888888y  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
 
点击右上角即可分享
微信分享提示