(intermediate) 双向bfs UVA 11212 Editing a Book

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());
	}
}


 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值