版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84517810
问题描述:
给定两个方格阵列组成的图形A和图形B,每个方格的颜色为黑色或白色,如下图所示。行列变换问题的每一步变换可以交换任意2行或2列方格的颜色,或者将某行或某列颠倒。上述每次变换算作一步。试设计一个算法,计算最少需要多少步,才能将图形A变换为图形B。
解题思路:
(1)使用先进先出队列式分支限界法
(2)将每个格局使用一个int变量表示
(3)将各种变换转换为位运算
下面给出基于上述思路的代码:
//行列变换问题
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int MAX = 5;
int beg, tar, cnt[1 << MAX * MAX];
//返回x >= 0行y >= 0对应的位, 最低位对应第0位
int p(int x, int y){
return 4 * x + y;
}
//交换sta的第pos1位和第pos2位
void swapD(int &sta, int pos1, int pos2){
int a = sta >> pos1 & 1, b = sta >> pos2 & 1;
if(b) sta |= 1 << pos1; else sta &= ~(1 << pos1);
if(a) sta |= 1 << pos2; else sta &= ~(1 << pos2);
}
//交换sta的第i行和第j行
void swapR(int &sta, int i, int j){
for(int k = 0; k < 4; ++k) swapD(sta, p(i, k), p(j, k));
}
//交换sta的第i列和第j列
void swapC(int &sta, int i, int j){
for(int k = 0; k < 4; ++k) swapD(sta, p(k, i), p(k, j));
}
//将sta的第i行颠倒
void reR(int &sta, int i){
swapD(sta, p(i, 0), p(i, 3)), swapD(sta, p(i, 1), p(i, 2));
}
//将sta的第i列颠倒
void reC(int &sta, int i){
swapD(sta, p(0, i), p(3, i)), swapD(sta, p(1, i), p(2, i));
}
int main(){
//输入起始状态
for(int i = 0, t; i < 4; ++i)
for(int j = 0; j < 4; ++j){
cin >> t; if(t) beg ^= 1 << p(i, j);
}
//输入目标状态
for(int i = 0, t; i < 4; ++i)
for(int j = 0; j < 4; ++j){
cin >> t; if(t) tar ^= 1 << p(i, j);
}
//执行BFS
memset(cnt, 0, sizeof(cnt)); queue<int> qu;
cnt[beg] = 1, qu.push(beg);
while(!qu.empty()){
int t = qu.front(); qu.pop();
//行交换
for(int i = 0; i < 4; ++i)
for(int j = i + 1; j < 4; ++j){
int tmp = t; swapR(tmp, i, j);
if(!cnt[tmp] || cnt[t] + 1 < cnt[tmp])
cnt[tmp] = cnt[t] + 1, qu.push(tmp);
}
//列交换
for(int i = 0; i < 4; ++i)
for(int j = i + 1; j < 4; ++j){
int tmp = t; swapC(tmp, i, j);
if(!cnt[tmp] || cnt[t] + 1 < cnt[tmp])
cnt[tmp] = cnt[t] + 1, qu.push(tmp);
}
//行颠倒
for(int i = 0; i < 4; ++i){
int tmp = t; reR(tmp, i);
if(!cnt[tmp] || cnt[t] + 1 < cnt[tmp])
cnt[tmp] = cnt[t] + 1, qu.push(tmp);
}
//列颠倒
for(int i = 0; i < 4; ++i){
int tmp = t; reC(tmp, i);
if(!cnt[tmp] || cnt[t] + 1 < cnt[tmp])
cnt[tmp] = cnt[t] + 1, qu.push(tmp);
}
}
cout << cnt[tar] - 1 << endl;
return 0;
}
运行截图: