有一个H行W列的矩阵,记n=H*W
,每个格子分别有个[1,n]内的数字,对应1~n
的一个排列。每次可以选择大小为(H-1)*(W-1)
的子矩阵旋转180度。
给定初始状态,问20步以内是否可以将它还原为1~n
的排列?如果可以,输出最小步数,否则输出-1。
3<=H,W<=8; 1<=a[i][j]<=H*W; a[i][j]各不相等
bfs搜索,由于每一步都有4种情况,时间复杂度为O(4^20)
,会TLE,因此改用双向bfs,时间复杂度降为O(2*4^10)
,可以通过。需要用哈希来判重。
#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--)
const int b1 = 409, m1 = 1000000409;
const int b2 = 439, m2 = 1000000439;
const int b3 = 433, m3 = 1000000433;
using node = array<array<int,9>,9>;
using hval = tuple<int,int,int>;
void solve() {
int H, W;
cin >> H >> W;
node s{}, t{};
map<hval,int> ms, mt;
rep(i,1,H) rep(j,1,W) cin >> s[i][j];
rep(i,1,H) rep(j,1,W) t[i][j] = (i-1)*W+j;
auto rotate = [&](const node &u, node &v, int x, int y) {
v = u;
rep(i,1,H-1) rep(j,1,W-1) {
v[i+x][j+y] = u[H-i+x][W-j+y];
}
};
auto id = [&](const node &u) -> hval {
int h1 = 0, h2 = 0, h3 = 0;
rep(i,1,H) rep(j,1,W) {
h1 = (h1 * b1 + u[i][j]) % m1;
h2 = (h2 * b2 + u[i][j]) % m2;
h3 = (h3 * b3 + u[i][j]) % m3;
}
return {h1,h2,h3};
};
auto bfs = [&](node u, map<hval,int> &mp) -> void {
int step = 0;
queue<node> q;
q.push(u);
while (!q.empty() && step <= 10) {
int cnt = q.size();
node x{}, y{};
rep(i,1,cnt) {
x = q.front(); q.pop();
mp[id(x)] = step;
rep(i,0,1) rep(j,0,1) {
rotate(x, y, i, j);
if (mp.count(id(y)) == 0) {
q.push(y);
}
}
}
step += 1;
}
};
bfs(s, ms);
bfs(t, mt);
int ans = 100;
for (auto &[k,v] : mt) {
auto it = ms.find(k);
if (it != ms.end()) {
ans = min(ans, v + it->second);
}
}
if (ans == 100) {
ans = -1;
}
cout << ans;
}
signed main() {
cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。