hihocoder offer收割19th 数组重排3 hiho1539
哈哈,利用宽度优先搜索,求初态移到有序终态的最少步数。由于最多八个数字,8是个很好的数字,刚好可以用3个bit位存下不大于8的数字,8个不大于的数字可以用24比特位存下(一个int类型就可以存下一个数组的状态了~)。所有状态不可能超过数组长度的阶乘,因为有的状态达不到。比如21,不可能转化为12。
(43210)D 这个序列就可以用 43210 八进制表示,
难就难在状态转化的位操作上。01片段截取重组,
而且ALU进行的是算术移位,左移把高位溢出掉然后右移,高位会出现很多一(按位补),右移挤掉低位再左移补0,这道没啥影响。
对了,用一个数组记录所宽搜过的状态,所有可能的状态都搜过后,还不能达到目标,就无解。
#1539 : 数组重排3
时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
-
-
描述
- 给定一个{
1..N}的排列A1,A2, ...A``N,每一次操作可以将相邻的两个数一起移动(保持两个数相邻且前后顺序不变)到任意位置。询问至少经过多少次操作,可以使得原序列变为1, 2, ...,N。 - 例如对于54321,把32一起移动到最左端得到32541;再把25一起移动到最右端得到34125;再把12一起移动到最左端得到12345。
-
输入
- 第1行:1个正整数
T,表示输入数据的组数 - 第2..
T+1行:每行一个字符串,表示初始排列 - 对于30%的数据:
T= 1, 1 ≤N≤ 5 - 对于100%的数据:1 ≤
T≤ 5, 1 ≤N≤ 8 -
输出
- 第1..
T行:每行一个整数,第i行表示第i个排列变化为1, 2, ...,N所需要的最少步数。若无可行方案,输出"-1"。 - 样例输入
-
2 54321 321 - 样例输出
-
3 -1
-
我用的八进制操作,debug只能输出中间结果,其中oct是将输出八进制。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <queue>
#include <cstring>
using namespace std;
#define FF 0xFFFFFFFF
typedef pair<int, int> type;
int state = 0, des, len;
bool vis[16777216];//2^24
int BFS(int st, int dep) {
if (st == des) return dep;
queue<type> q;
q.push(make_pair(st, dep));
memset(vis, 0, sizeof vis);
vis[st] = true;
while (!q.empty()) {
type sta = q.front(); q.pop();
st = sta.first;
for (int i = 1; i < len; ++i) { //7 6 5 4 3 2 1 0//i是截取位
int x = 0x3f << (i - 1) * 3;//6个1
//cout << oct << x << endl;
x = (x & st) >> (i - 1) * 3;//截取6位
long long high = st >> (i + 1) * 3 << (i + 1) * 3;//剩余高位
int low = (int)(((long long)st << (32 - (i - 1) * 3) & FF) >> (32 - (i - 1) * 3)); //想要的溢出
//cout << i << " " << oct << st << " " << oct << x << " " << oct << high << " " << oct << low << endl;//debug
for (int in = 0; in <= len; ++in) { //in是插入位
if (in == i + 1 || in == i || in == i - 1) continue; //在三个位置插入没意义
int stat;
if (in < i) {
int lower = (int)(((long long)low << (32 - in * 3) & FF) >> (32 - in * 3));
//cout << oct << lower << endl;
stat = low >> in * 3 << in * 3 + 6; // cout << oct << stat << endl;
stat |= high; // cout << oct << stat << endl;
stat |= x << in * 3; // cout << oct << stat << endl;
stat |= lower;
}
else { // in > i 在左边插入
int lower = (int)((high << (32 - in * 3) & FF) >> (38 - in * 3));
//cout << oct << lower << endl;//需要的是逻辑右移
stat = high >> in * 3 << in * 3;
stat |= x << (in - 2) * 3;
stat |= lower;
stat |= low;
}
//cout << oct << stat << endl;
if (!vis[stat]) {
if (stat == des) return sta.second + 1;
vis[stat] = true;
q.push(make_pair(stat, sta.second + 1));
}
}
}
}
return -1;
}
int main()
{
//freopen("D:/coding/Dev/data.in", "r", stdin);
ios::sync_with_stdio(false);
int T;
cin >> T;
while (T--) {
string str;
cin >> str;
len = str.length();
state = des = 0;
for (int i = 0; i < len; ++i) {
state |= (str[len - 1 - i] - '1') << (i * 3);
des |= i << ((len - 1 - i) * 3);
}
//cout << oct << state << " " << oct << des << endl;//debug
cout << BFS(state, 0) << endl;
}
return 0;
}
\
\
\