当前位置:网站首页>信息学奥赛一本通T1451:棋盘游戏
信息学奥赛一本通T1451:棋盘游戏
2022-08-03 05:30:00 【thank有】
信息学奥赛一本通T1451:棋盘游戏
【题目描述】
在一个 4×4 的棋盘上有 8 个黑棋和 8 个白棋,当且仅当两个格子有公共边,这两个格子上的棋是相邻的。移动棋子的规则是交换相邻两个棋子。
给出一个初始棋盘和一个最终棋盘,请找出一个最短的移动序列使初始棋盘变为最终棋盘。
【输入】
前四行,每行 4 个数字(1 或者 0 ),描述了初始棋盘;
接着是一个空行;
第六到第九行,每行 4 个数字(1 或者 0),描述了最终棋盘。
【输出】
一行是一个整数 n,表示最少的移动步数。
【输入样例】
1111
0000
1110
00101010
0101
1010
0101【输出样例】
4
思路:
本题是要从一个大状态变到另一个大状态,并且求其最小步数,很容易看出应用 BFS 来做
可以看出,每个单元非 0 即 1,共有 16 个单元,这样可以将每个棋盘当做一个 16 位的二进制数,将其转为十进制后再存储状态,最多有 2^16=65535 种状态
对于每种状态,由高到低枚举每个位置,计算该位置在棋盘上的坐标 (x,y),理论上来说,格子可与其上下左右相邻的四个格子任意进行交换,但显然,但采用异或运算交换两个相邻格子时,对每个格子四方向的枚举互换会造成大量的重复,因此,只要对每个格子从上到下,从左到右去尝试互换即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL multMod(LL a,LL b,LL mod){ a%=mod; b%=mod; LL res=0; while(b){if(b&1)res=(res+a)%mod; a=(a<<=1)%mod; b>>=1; } return res%mod;}
LL quickMultPowMod(LL a, LL b,LL mod){ LL res=1,k=a; while(b){if((b&1))res=multMod(res,k,mod)%mod; k=multMod(k,k,mod)%mod; b>>=1;} return res%mod;}
LL quickPowMod(LL a,LL b,LL mod){ LL res=1; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1; } return res; }
LL getInv(LL a,LL mod){ return quickPowMod(a,mod-2,mod); }
LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); }
LL LCM(LL x,LL y){ return x/GCD(x,y)*y; }
const double EPS = 1E-6;
const int MOD = 1000000000+7;
const int N = 1000+5;
const int dx[] = {0,0,-1,1,1,-1,1,1};
const int dy[] = {1,-1,0,0,-1,1,-1,1};
using namespace std;
struct Node {
int val;
int step;
Node() {}
Node(int val, int step) : val(val), step(step) {}
};
int vis[65536 + 10];
void BFS(Node st, Node ed) {
memset(vis, 0, sizeof(vis));
queue<Node> Q;
Q.push(st);
while (!Q.empty()) {
Node now = Q.front();
Q.pop();
if (now.val == ed.val) {
cout << now.step << endl;
return;
}
int val = now.val;
int step = now.step;
for (int i = 15; i >= 0; i--) { //从高到低枚举每一位
int x = (15 - i) / 4, y = (15 - i) % 4; //横纵坐标
int nowPos = 1 << i; //当前位置代表权值
int rightPos = 1 << (i - 1); //当前位置右方位置代表权值
int downPos = 1 << (i - 4); //当前位置下方位置代表权值
if (y < 3 && ((val & nowPos) != (val & rightPos))) { //向右交换
int nextVal = val ^ nowPos ^ rightPos; //交换后的状态
if (!vis[nextVal]) {
vis[nextVal] = true;
Q.push(Node(nextVal, step + 1));
}
}
if (x < 3 && ((val & nowPos) != (val & downPos))) { //向下交换
int nextVal = val ^ nowPos ^ downPos; //交换后的状态
if (!vis[nextVal]) {
vis[nextVal] = true;
Q.push(Node(nextVal, step + 1));
}
}
}
}
}
int main() {
char ch;
int st = 0, ed = 0;
for (int i = 15; i >= 0; i--) {
cin >> ch;
if (ch == '1')
st += 1 << i;
}
for (int i = 15; i >= 0; i--) {
cin >> ch;
if (ch == '1')
ed += 1 << i;
}
if (st == ed)
printf("0\n");
else
BFS(Node(st, 0), Node(ed, 0));
return 0;
}【源程序】
边栏推荐
猜你喜欢

【onnx 输入尺寸】修改pytorch生成的onnx模型的输入尺寸

5G网络入门基础--5G网络的架构与基本原理

SQL——左连接(Left join)、右连接(Right join)、内连接(Inner join)

MySQL的安装教程(嗷嗷详细,包教包会~)

高密度 PCB 线路板设计中的过孔知识

MySQL的Replace用法详解

【dllogger bug】AttributeError: module ‘dllogger‘ has no attribute ‘StdOutBackend‘

MySQL的DATE_FORMAT()函数将Date转为字符串

【地平线 开发板】实现模型转换并在地平线开发板上部署的全过程操作记录(魔改开发包)

Redis-记一次docker下使用redis
随机推荐
【设计指南】避免PCB板翘,合格的工程师都会这样设计!
MySQL的Replace用法详解
CCF NOI 2022笔试题库
ES6 - 剩余参数,Array的扩展方法,String的扩展方法
MySQL中的行锁
nacos-2.0.3启动报错出现no datasource set的坑
Cesium加载离线地图和离线地形
postman配置中文
pyspark --- 空串替换为None
JDBC从手写连接到引用DBCP和C3P0
【云原生 · Kubernetes】搭建Harbor仓库
el-tree设置选中高亮焦点高亮、选中的节点加深背景,更改字体颜色等
docker-compose部署mysql
ES6中 async 函数、await表达式 的基本用法
IPV4地址详解
单节点部署 gpmall 商城系统(一)
5 个开源的 Rust Web 开发框架,你选择哪个?
MySQL的DATE_FORMAT()函数将Date转为字符串
ES6中 Symbol 的基础学习,迭代器和生成器的基本用法
高密度 PCB 线路板设计中的过孔知识