题意:给你一串n个数字,你可以对其中的一些连续片段进行剪切和粘贴的操作,然后用最小的步数使得这个序列变为1-n排列。
思路:这个题目就是对于DFS进行大量的剪枝的操作,一组序列最多进行八次操作就可以让其变为目标的序列,然后如果对于一个片段进行操作的话,最多能减少一个序列当中的三个错误,我们根据这个地方进行剪枝,可以大大减少时间的复杂度。剩下的部分枚举就好了。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <list>
#define MAXN 210
#define INF 10000000
#define MOD 1000000007
#define LL long long
#define pi acos(-1.0)
using namespace std;
int book[MAXN];
int n;
bool check() {
for (int i = 0; i < n; ++i)
if (book[i] != i + 1)
return false;
return true;
}
int falut_num() {
int ans = 0;
for (int i = 0; i < n - 1; ++i) {
if (book[i] + 1 != book[i + 1])
ans++;
}
if (book[n - 1] != n)
ans++;
return ans;
}
bool dfs(int d, int maxn) {
if (d + falut_num() > maxn)
return false;
if (check())
return true;
int old_book[MAXN];
int past_to[MAXN];
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
memcpy(old_book, book, sizeof(book));
int cnt = 0;
for (int k = 0; k < n; k++)
if (k < i || k > j)
past_to[cnt++] = book[k];
for (int k = 0; k <= cnt; k++) {
int cnt2 = 0;
for (int p = 0; p < k; p++)
book[cnt2++] = past_to[p];
for (int p = i; p <= j; p++)
book[cnt2++] = old_book[p];
for (int p = k; p < cnt; p++)
book[cnt2++] = past_to[p];
if (dfs(d + 1, maxn))
return true;
memcpy(book, old_book, sizeof(old_book));
}
}
}
return false;
}
int main() {
std::ios::sync_with_stdio(false);
int kase = 0;
while (cin >> n && n) {
for (int i = 0; i < n; ++i)
cin >> book[i];
int ans = -1;
for (int i = 0; i <= 9; ++i) {
if (dfs(0, i)) {
ans = i;
break;
}
}
cout << "Case " << ++kase << ": " << ans << endl;
}
return 0;
}