Problem E
Editing a Book
You have n equal-length paragraphs numbered 1 to n. Now you want to arrange them in the order of 1, 2, ...,n. With the help of a clipboard, you can easily do this: Ctrl-X (cut) and Ctrl-V (paste) several times. You cannot cut twice before pasting, but you can cut several contiguous paragraphs at the same time - they'll be pasted in order.
For example, in order to make {2, 4, 1, 5, 3, 6}, you can cut 1 and paste before 2, then cut 3 and paste before 4. As another example, one copy and paste is enough for {3, 4, 5, 1, 2}. There are two ways to do so: cut {3, 4, 5} and paste after {1, 2}, or cut {1, 2} and paste before {3, 4, 5}.
Input
The input consists of at most 20 test cases. Each case begins with a line containing a single integer n (1 <n < 10), the number of paragraphs. The next line contains a permutation of 1, 2, 3,..., n. The last case is followed by a single zero, which should not be processed.
Output
For each test case, print the case number and the minimal number of cut/paste operations.
Sample Input
6 2 4 1 5 3 6 5 3 4 5 1 2 0
Output for the Sample Input
Case 1: 2 Case 2: 1
Rujia Liu's Present 2: A Big Contest of Brute Force
Adapted from ACM/ICPC Kanpur Site 2001-2001
题意:有一段序列,一开始是1234567...n,你需要经过最少的操作让他变成目标序列。操作是将连续的一段插入到序列的任意一个位置。
思路:这道题目直接bfs会超时的,状态的话由于最多只有9!次,可以用数组存起来判重,我们要用双向的宽搜,我们先正的搜一层,然后反向搜一层,当他们接触到了,结果就出来了。
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<string.h>
#include<algorithm>
#include<list>
#include<vector>
using namespace std;
const int maxn = 11;
const int maxs = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 2;
int fact[maxn];
int n;
int t;
bool visit[11];
int buf[maxn];
struct State
{
int v[maxn];
void insert(int l, int r, int p)
{
memcpy(buf, v + l, sizeof(int)*(r - l + 1));
if (l > p) {
// v.erase(v.begin() + l, v.begin() + r + 1);
memmove(v + r - (l - p - 1) + 1, v + p + 1, 4 * (l - p - 1));
memmove(v + p + 1, buf, 4 * (r - l + 1));
// v.insert(v.begin() + (1 + p), buf.begin(), buf.end());
}
else if (p > r) {
memmove(v + l, v + r + 1, 4 * (p - r));
memmove(v + l + p - r, buf, 4 * (r - l + 1));
/*v.insert(v.begin() + p + 1, v.begin() + l, v.begin() + r + 1);
v.erase(v.begin() + l, v.begin() + r + 1);*/
}
}
int hash() const
{
int ret = 0;
memset(visit, 0, sizeof(visit));
for (int i = 0; i < n; ++i) {
int cnt = 0;
for (int j = i + 1; j < n; ++j)
if (v[i]>v[j]) ++cnt;
ret += fact[n - i - 1] * cnt;
}
return ret;
}
void out() const
{
for (int i = 0; i < n; ++i) printf(" %2d", v[i]);
puts("");
}
};
State target;
int d[2][maxs];
State q[2][maxs];
int front[2], rear[2];
int bfs()
{
int cur = 0;
for (int i = 0; i < 2; ++i) front[i] = rear[i] = 0;
memset(d, -1, sizeof(d));
State start;
for (int i = 0; i < n; ++i) start.v[i] = i + 1;
int x = start.hash(); d[cur][x] = 0, d[cur ^ 1][t] = 0;
q[cur][rear[cur]++] = start;
q[cur ^ 1][rear[cur ^ 1]++] = target;
State tmp, now;
int dep[2] = { 0, 0 };
while (true) {
/* if (rear[cur ^ 1] - front[cur ^ 1] < rear[cur] - front[cur])
cur ^= 1;*/
if (front[cur] >= rear[cur]) cur ^= 1;
if (front[cur] >= rear[cur]) break;
tmp = q[cur][front[cur]++];
x = tmp.hash();
if (d[cur][x] > dep[cur]) {
dep[cur] = d[cur][x];
cur ^= 1;
continue;
}
if (d[cur ^ 1][x] != -1) {
// tmp.out();
return d[cur][x] + d[cur ^ 1][x];
}
for (int l = 0; l < n; ++l)
for (int r = l; r < n; ++r) {
for (int k = -1; k < n; ++k) {
if (l <= k&&k <= r) continue;
now = tmp;
// now.out();
now.insert(l, r, k);
// now.out();
// puts("");
int y = now.hash();
if (d[cur][y] != -1) continue;
d[cur][y] = d[cur][x] + 1;
q[cur][rear[cur]++] = now;
}
}
}
}
void GetData()
{
int a[10];
for (int i = 0; i < 9; ++i) a[i] = i + 1;
freopen("in.txt", "w", stdout);
do {
printf("9\n");
for (int i = 0; i < 9; ++i) printf("%d ", a[i]);
printf("\n");
} while (next_permutation(a, a + 9));
printf("0\n");
}
int main()
{
// GetData(); return 0;
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
fact[0] = 1;
for (int i = 1; i <= 10; ++i) fact[i] = fact[i - 1] * i;
int cas = 0;
while (scanf("%d", &n), n) {
target = State();
++cas;
for (int i = 0; i < n; ++i) {
int x; scanf("%d", &x);
target.v[i] = x;
}
t = target.hash();
printf("Case %d: %d\n", cas, bfs());
}
}