pku3460 Booksort
给定一个序列,每次可取出一段任意长度的序列插到某个位置,问至少多少次操作能让序列变为1.2.3.4......n。如果步数超过4,输出“5 or more”
可以用双向BFS,但编程复杂度较高,用迭代加深就需要动一点脑筋想强剪枝。
题目的最终状态是1 2 3 4 5 6 7 8,则严格递增序列为1。所谓严格递增即是说1 2 3 4 5 6,这些,而2 5,2 4 6,这种只能称之为递增,
那么1 2 5 6 3 4 7 8的严格递增序列有4个,
而每次操作最多一次减少3个非严格递增序列,所以有这个剪枝:if 当前递增序列个数-3*(最大深度-当前深度)>=0 then exit
加入这个剪枝不一定能AC,序列的重构一定要写的好一点,如果用n^4的操作,绝对超时。
顺便说一下,代码里的chaneg(i,j,k)表示把当前状态中(i..j)这个序列移动到第k个元素后面。
View Code
1 program pku3460(input,output);
2 type
3 numbertype = array[0..16] of integer;
4 var
5 state : numbertype;
6 n,sum : integer;
7 depth : integer;
8 flag : boolean;
9 v,cases : integer;
10 function check(a: numbertype ):integer;
11 var
12 sum,i : integer;
13 begin
14 sum:=0;
15 for i:=1 to n-1 do
16 if a[i+1]<>a[i]+1 then
17 inc(sum);
18 exit(sum+1);
19 end; { check }
20 procedure init;
21 var
22 i : integer;
23 begin
24 readln(n);
25 for i:=1 to n do
26 read(state[i]);
27 end; { init }
28 procedure change(x,y,z :longint );
29 var
30 i,now : longint;
31 tmp : numbertype;
32 begin
33 fillchar(tmp,sizeof(tmp),0);
34 for i:=1 to x-1 do
35 tmp[i]:=state[i];
36 now:=x-1;
37 for i:=y+1 to z do
38 begin
39 inc(now);
40 tmp[now]:=state[i];
41 end;
42 for i:=x to y do
43 begin
44 inc(now);
45 tmp[now]:=state[i];
46 end;
47 for i:=z+1 to n do
48 tmp[i]:=state[i];
49 state:=tmp;
50 end; { change }
51 procedure dfs(now: integer );
52 var
53 i,j,k : integer;
54 tmp : numbertype;
55 begin
56 if now>depth then
57 exit;
58 for i:=1 to n do
59 if state[i]>state[i+1] then
60 break;
61 if i=n then
62 flag:=true;
63 sum:=check(state);
64 if (sum-3*(depth-now+1)>=0) then
65 exit;
66 if flag then
67 exit;
68 tmp:=state;
69 for i:=1 to n-1 do
70 for j:=i to n-1 do
71 for k:=j+1 to n do
72 begin
73 change(i,j,k);
74 dfs(now+1);
75 state:=tmp;
76 if flag then
77 exit;
78 end;
79 end; { dfs }
80 procedure main;
81 begin
82 for depth:=0 to 4 do
83 begin
84 flag:=false;
85 dfs(0);
86 if flag then
87 break;
88 end;
89 if flag then
90 writeln(depth)
91 else
92 writeln('5 or more');
93 end; { main }
94 begin
95 readln(cases);
96 for v:=1 to cases do
97 begin
98 init;
99 main;
100 end;
101 end.