You have n equal-length paragraphs numbered 1 to n. Now you want to arrange them in the orderof 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 atthe 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 andpaste before 4. As another example, one copy and paste is enough for {3, 4, 5, 1, 2}. There are twoways 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), thenumber of paragraphs. The next line contains a permutation of 1, 2, 3, . . . , n. Thelast case is followed by a single zero, which should not be processed.
Ouput
For each test case, print the case number and the minimal number of cut/paste operations.
枚举区间,用IDA*算法剪枝即可。
第一次写这题的时候,总感觉是有什么数学方法能直接解决,想不到了就只有dfs暴力了咯,第一次写时弄错启发函数了,直接超时,参考了刘老师的启发函数才过掉。
中间其实有个技巧,粘贴复制的过程其实相当于两个相邻子区间的互换。互换只要从前往后换即可,因为向前与向后是整体对称的。
还有一点需要强调,bool类型函数默认返回true值而不是false值,我已经两次搞错了,心累啊T_T
AC代码(0ms)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdlib>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<sstream>
#include<utility>
#include<ctype.h>
using namespace std;
typedef pair<int,int> Pair;
/* G++ 5.1.0 */
int num[10], a[10];
int maxn, n;
int h() {
int cnt = 0;
for(int i=0; i<n-1; i++)
if(a[i]+1 != a[i+1]) cnt ++;
if(a[n-1] != n) cnt ++;
return cnt;
}
bool dfs(int beg) {
if(beg == maxn) {
if(h()==0) return true;
return false;
}
if(3*beg + h() > 3*maxn) return false;
int olda[10], suba[10], subb[10];
memcpy(olda, a, sizeof(a));
for(int i=0; i<n; i++)
for(int j=i; j<n; j++) {
int cnt1 = 0;
for(int k=i; k<=j; k++) suba[cnt1++] = olda[k];
for(int k=j+1; k<n; k++) {
int cnt2 = 0;
for(int t=j+1; t<=k; t++) subb[cnt2++] = olda[t];
int c1 = 0, c2 = 0;
for(int t=0; t<n; t++) {
if(t<i) a[t] = olda[t]; else
if(t<i+cnt2) a[t] = subb[c1++]; else
if(t<i+cnt2+cnt1) a[t] = suba[c2++]; else
a[t] = olda[t];
}
if(dfs(beg+1)){
return true;
}
}
}
return false;
}
int main() {
int kase = 0;
while(scanf("%d", &n) && n) {
maxn = 0;
int na[10];
for(int i=0; i<n; i++) scanf("%d", &na[i]);
memcpy(a, na, sizeof(na));
printf("Case %d: ", ++kase);
if(h()==0) printf("0\n"); else
{
for(maxn=1; maxn<5; maxn++) {
memcpy(a, na, sizeof(na));
if(dfs(0)) break;
}
}
if(maxn) {
printf("%d\n", maxn);
}
}
}