pku3460 Booksort
2012-03-17 10:49
148 查看
给定一个序列,每次可取出一段任意长度的序列插到某个位置,问至少多少次操作能让序列变为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
可以用双向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
program pku3460(input,output); type numbertype = array[0..16] of integer; var state : numbertype; n,sum : integer; depth : integer; flag : boolean; v,cases : integer; function check(a: numbertype ):integer; var sum,i : integer; begin sum:=0; for i:=1 to n-1 do if a[i+1]<>a[i]+1 then inc(sum); exit(sum+1); end; { check } procedure init; var i : integer; begin readln(n); for i:=1 to n do read(state[i]); end; { init } procedure change(x,y,z :longint ); var i,now : longint; tmp : numbertype; begin fillchar(tmp,sizeof(tmp),0); for i:=1 to x-1 do tmp[i]:=state[i]; now:=x-1; for i:=y+1 to z do begin inc(now); tmp[now]:=state[i]; end; for i:=x to y do begin inc(now); tmp[now]:=state[i]; end; for i:=z+1 to n do tmp[i]:=state[i]; state:=tmp; end; { change } procedure dfs(now: integer ); var i,j,k : integer; tmp : numbertype; begin if now>depth then exit; for i:=1 to n do if state[i]>state[i+1] then break; if i=n then flag:=true; sum:=check(state); if (sum-3*(depth-now+1)>=0) then exit; if flag then exit; tmp:=state; for i:=1 to n-1 do for j:=i to n-1 do for k:=j+1 to n do begin change(i,j,k); dfs(now+1); state:=tmp; if flag then exit; end; end; { dfs } procedure main; begin for depth:=0 to 4 do begin flag:=false; dfs(0); if flag then break; end; if flag then writeln(depth) else writeln('5 or more'); end; { main } begin readln(cases); for v:=1 to cases do begin init; main; end; end.
相关文章推荐
- POJ 3460 Booksort
- POJ 3460 Booksort
- 关于windows编程的一些心得 选择自 forpku 的 Blog
- 今天的网络比以前正常了一点。总算可以到PKU上做题目了!PKU2896“Changing Phone Numbers”
- Team Blog PKU Wings
- 有趣的加法(解pku1014的关键)
- Soundex pku 2608
- 转 pku题目分类
- pku1125
- 487-3279 - PKU 1002
- PKU2486所谓树型DP
- PKU3264线段树解法
- Pku acm 2533 Longest Ordered Subsequence 动态规划题目解题报告(十二)
- Pku acm 2388 Who's in the Middle 排序算法解题报告(二)----计数排序
- Pku acm 2406 Power Strings数据结构题目解题报告(十八)----kmp算法
- PKU3385 Genealogy
- PKU 1012 Joseph
- PKU 2853 Sequence Sum Possibilities
- PKU 1061 (扩展欧几里德)
- ACM基本算法分类、推荐学习资料和配套pku习题