题面:给定两个H行W列的矩阵A和B,每次操作可以交换相邻的行或列,问是否可以将A变成B?如果可以,输出最少操作步数;如果不行,输出-1。
范围:2<=H,W<=5, 1<=A[i][j],B[i][j]<=1e9
思路:数据规模小,直接bfs搜索,如果范围再大点可以用双向bfs优化效率。需要用到哈希来快速判重。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a; i<=b; i++)
#define per(i,a,b) for(int i=b; i>=a; i--)
using hval = tuple<int,int,int>;
const int B1 = 131, M1 = 1000000123;
const int B2 = 137, M2 = 1000000223;
const int B3 = 139, M3 = 1000000007;
const int N = 6;
using Arr = array<array<int,N>,N>;
int H, W;
Arr A, B;
hval HB;
set<hval> vis;
hval encode(Arr a) {
int x = 0, y = 0, z = 0;
rep(i,1,H) rep(j,1,W) {
x = (x * B1 + a[i][j]) % M1;
y = (y * B2 + a[i][j]) % M2;
z = (z * B3 + a[i][j]) % M3;
}
return {x,y,z};
}
void bfs() {
HB = encode(B);
queue<tuple<Arr,hval,int>> q;
hval HA = encode(A);
q.push({A,HA,0}); vis.insert(HA);
while (!q.empty()) {
auto [t,h,d] = q.front(); q.pop();
if (h == HB) {
cout << d << "\n";
return;
}
rep(i,1,H-1) {
Arr x = t;
rep(j,1,W) swap(x[i][j], x[i+1][j]);
hval hx = encode(x);
if (vis.count(hx) == 0) {
q.push({x,hx,d+1}); vis.insert(hx);
}
}
rep(j,1,W-1) {
Arr x = t;
rep(i,1,H) swap(x[i][j], x[i][j+1]);
hval hx = encode(x);
if (vis.count(hx) == 0) {
q.push({x,hx,d+1}); vis.insert(hx);
}
}
}
cout << -1 << "\n";
}
void solve() {
cin >> H >> W;
rep(i,1,H) rep(j,1,W) cin >> A[i][j];
rep(i,1,H) rep(j,1,W) cin >> B[i][j];
bfs();
}
signed main() {
cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
标签:const,abc332D,int,hval,rep,矩阵,cin,bfs,步数
From: https://www.cnblogs.com/chenfy27/p/18060737