Description
汉诺塔升级了:现在我们有 \(N\) 个圆盘和 \(N\) 个柱子,每个圆盘大小都不一样,大的圆盘不能放在小的圆盘上面,\(N\) 个柱子从左到右排成一排。每次你可以将一个柱子上的最上面的圆盘移动到右边或左边的柱子上(如果移动之后是合法的话)。先在告述你初始时的状态,你希望用最少的步数将第 \(i\) 大的盘子移动到第 \(i\) 根柱子上,问最小步数。
Input
第一行一个正整数 \(T\) ,代表询问的组数。
接下来 \(T\) 组数据,每组数据第一行一个整数 \(N\) 。
接下来一行每行 \(N\) 个正整数,代表每个柱子上圆盘的大小。
Output
输出共 \(T\) 行,代表每次的答案。如果方案不存在,输出 \(-1\) 。
Sample
Sample Input
4
3
2 1 3
2
7 8
2
10000 1000
3
97 96 95
Sample Output
4
0
-1
20
Limit
对于 \(70\%\) 的数据, \(N\) 的值都是相等的。
对于 \(100\%\) 的数据, \(1\le T\le 6\times 10^3,1\le N\le 7\) 。
Solution
因为 \(N\) 很小,所以可以通过bfs
状压 \(\mathrm{dp}\) 把每种情况预处理出来,直接查询。
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
inline int read() {
int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}
struct data{ int v, id; }a[10]; int b[10], c[10];
bool cmp(const data& x, const data& y) { return x.v < y.v; }
int ans[8000000], m[10] = { 1 }, p[10], top[10];
bool tag[8000000];
queue<int> q;
void insert(int s) {
int len = 0, tmp = s; while(tmp) p[++len] = tmp % 10, tmp /= 10; reverse(p + 1, p + 1 + len);
memset(top, 0, sizeof top); for (int i = len; i; i--) top[p[i]] = i;
rep(i, 1, len) if(i == top[p[i]]) {
if(p[i] != 1 && (top[p[i] - 1] > i || !top[p[i] - 1])) {
int t = s - m[len - i]; if(!tag[t]) ans[t] = ans[s] + 1, q.push(t), tag[t] = 1;
}
if(p[i] != len && (top[p[i] + 1] > i || !top[p[i] + 1])) {
int t = s + m[len - i]; if(!tag[t]) ans[t] = ans[s] + 1, q.push(t), tag[t] = 1;
}
}
}
void init() {
int s = 0;
rep(i, 1, 7) m[i] = m[i - 1] * 10, s = s * 10 + i, q.push(s), tag[s] = 1;
while(!q.empty()) insert(q.front()), q.pop();
}
int main() {
freopen("long.in", "r", stdin); freopen("long.out", "w", stdout);
init();
int T; T = read();
while(T--) {
int n = read(), s = 0;
rep(i, 1, n) a[i].v = read(), a[i].id = i;
sort(a + 1, a + 1 + n, cmp);
rep(i, 1, n) b[a[i].id] = i;
rep(i, 1, n) c[b[i]] = i;
rep(i, 1, n) s = s * 10 + c[i];
printf("%d\n", tag[s] ? ans[s] : -1);
}
return 0;
}