题目: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;
}
总结:做这题需要有强大的知识储备
做不出来的建议重修位运算
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具