求IOI96魔板问题的解法

Kusk 2005-12-09 12:41:06
在成功地发明了魔方之后,拉比克先生发明了它的二维版本,称作魔板。这是一张有8个大小相同的格子的魔板:

1 2 3 4
8 7 6 5

我们知道魔板的每一个方格都有一种颜色。这8种颜色用前8个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。对于上图的魔板状态,我们用序列(1,2,3,4,5,6,7,8)来表示。这是基本状态。

这里提供三种基本操作,分别用大写字母“A”,“B”,“C”来表示(可以通过这些操作改变魔板的状态):

“A”:交换上下两行;
“B”:将最右边的一行插入最左边;
“C”:魔板中央作顺时针旋转。
下面是对基本状态进行操作的示范:

A:
8 7 6 5
1 2 3 4
B:
4 1 2 3
5 8 7 6
C:
1 7 2 4
8 6 3 5


对于每种可能的状态,这三种基本操作都可以使用。

你要编程计算用最少的基本操作完成基本状态到特殊状态的转换,输出基本操作序列。

---------------------------------------------------
尽可能给出优化算法,如有源程序更佳,谢谢!
...全文
231 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
Kusk 2005-12-22
  • 打赏
  • 举报
回复
谢谢各位!
NowCan 2005-12-09
  • 打赏
  • 举报
回复
感觉和8数码问题差不多。
galois_godel 2005-12-09
  • 打赏
  • 举报
回复
广度优先搜索
mmmcd 2005-12-09
  • 打赏
  • 举报
回复

Program Magic;
Const
Size=8; { Size of the sheet }
M =40320; { =Size! }
Type
Trans =Array[1..Size] Of 1..Size;
Config=Array[1..Size] Of 1..Size;
Const
BT :Array['A'..'C'] Of Trans=((8,7,6,5,4,3,2,1), { basic transformations }
(4,1,2,3,6,7,8,5),
(1,7,2,4,5,3,6,8));
BT_1:Array['A'..'C'] Of Trans=((8,7,6,5,4,3,2,1), { inverses of the basic }
(2,3,4,1,8,5,6,7), { transformations }
(1,3,6,4,5,7,2,8));
Ini :Config=(1,2,3,4,5,6,7,8); { the initial configuration }
Var
T :Config; { the target configuration }
Answer:String; { the solution sequence of basic transformations }
Fact :Array[0..Size] Of Longint; { array of factorial values }
Last :Array[0..M] Of Char;
{ Last[Rank(T)] is the last character of a sequence of basic }
{ transformations that transforms the initial configuration to T. }
{ If Last[Rank(T)]=' ' then T has not been generated. }

Procedure ReadInput;
{ Global output variable: T }
Var InFile:Text;
i:Word;
Begin
Assign(InFile,'input.txt'); Reset(Infile);
For i:=1 To Size Do Read(Infile,T[i]);
Close(Infile);
End { ReadInput };

Procedure ComputeFact;
{ Computes the factorial values }
Var i:Word;
Begin
Fact[1]:=1;Fact[0]:=1;
For i:=2 To Size Do
Fact[i]:=i*Fact[i-1];
End;

Function Rank(Const P:Config): Word;
{ Rank(P) is the number of permutations that precedes P }
{ according to the lexicographic ordering. }
{ Global input variables: Size, Fact }
Var Res,l,i,j:Word;
Begin
Res:=0;
For i:=1 To Size Do Begin
l:=0; { l is the number of elements of P in positions }
{ 1..i-1 that are less than P[j] }
For j:=1 To i-1 Do
If P[j]<P[i] Then Inc(l);
{ Keeping fixed the first i-1 elements of P there can be (P[i]-1-l) }
{ numbers that are less than P[i] in position i in permutations. }
{ The number of permutations Q such that the first i-1 elements }
{ are the same as in P but Q precedes P in the lexicographic }
{ ordering is (P[i]-1-l)*Fact[Size-i]. }
Res:=Res+(P[i]-1-l)*Fact[Size-i];
End { For };
Rank:=Res;
End { Rank };

Procedure Apply(Const T:Config; X:Char; Var R:Config);
{ R is obtained by applying the basic transformation X }
{ to the configuration T }
Var i:Word;
Begin
For i:=1 To Size Do R[i]:=T[BT[X][i]];
End { Apply };

Procedure Apply_1(Const T:Config; X:Char; Var R:Config);
{ R is obtained by applying the inverse of the basic }
{ transformation X to the configuration T }
Var i:Word;
Begin
For i:=1 To Size Do R[i]:=T[BT_1[X][i]];
End {Apply_1};

Function Equal(Const R,T:Config): Boolean;
{ Checks equality of the configurations R and T }
Var i:Word;
Begin
i:=1;
While (i<=Size) And (R[i]=T[i]) Do Inc(i);
Equal:= i>Size;
End { Equal };

Procedure Generate(Const T: Config);
{ Generates a sequence of basic transformations that transforms the }
{ initial configuration to T. Last[Rank(T)] will be the last element of }
{ the sequence. }

{ Global input-output variable: Last }
Const
Qs=7000; { Queue size }
Var
Queue:Array[0..Qs-1] Of Config;
NotFound:Boolean;
Head,Tail:Word; { head and tail of the queue }
R,S: Config;
X: Char;

Procedure InitGener;
Var i:Word;
Begin
For i:=0 To M Do Last[i]:=' '; { initialize }
Last[0]:='.'; { 0=Rank(Ini), sentinel }
End;

Procedure InitQueue;
{ initialize the queue }
Begin
Head:=0; Tail:=1;
Queue[0]:=Ini; { put Ini into the queue }
End { InitQueue} ;

Procedure Enqueue(Const Q:Config);
Begin
Queue[Tail]:=Q;
Inc(Tail); If Tail=Qs Then Tail:=0;
End { Enqueue };

Procedure Dequeue(Var Q:Config);
Begin
Q:=Queue[Head];
Inc(Head); If Head=Qs Then Head:=0;
End { Dequeue };

Function NotMember(Const Q:Config; X:Char):Boolean;
{ Checks membership of Q in the set of generated configurations. }
{ If it is not generated then marks it as generated by setting the value }
{ of Last[Rank(Q)] to X. }
{ Global input-output variable: Last }
Var RankQ:Word;
Begin
RankQ:=Rank(Q);
If Last[RankQ]=' ' Then Begin
NotMember:=True;
Last[RankQ]:=X;
End Else
NotMember:=False;
End { NotMember };

Begin { Generate }
InitGener;
InitQueue;
NotFound:=True;
While NotFound Do Begin
Dequeue(R);
For X:='A' To 'C' Do Begin { apply all basic }
Apply(R, X, S); { transformations to R }
If NotMember(S,X) Then Begin { S is a new configuration }
If Equal(T,S) Then Begin { T=R*C decomposition found }
NotFound:= False;
Break; { exit the loop }
End;
Enqueue(S);
End { If new tr. };
End { For j };
End { While };
End { Generate };

Procedure Compose(Const T: Config; Var S:String);
{ Composes the sequence of basic transformations from the array Last }
{ following the link provided by the inverse transformation. }
{ Global input variable: Last }
Var
RankQ:Word; X:Char;
P,Q : Config;
Begin
Q:=T;
RankQ:=Rank(Q);
S:='';
While RankQ <> 0 Do Begin { while Q<>Ini }
X:=Last[RankQ];
S:=X+S; { append X to the left end of S }
Apply_1(Q,X,P); { Apply the inverse of X to Q }
Q:=P; { link to backward }
RankQ:=Rank(Q);
End { While };
End { Compose };

Procedure WriteOut;
{ Global input variable: Answer }
Var OutFile:Text;
L,i:Word;
Begin
Assign(OutFile,'output.txt'); Rewrite(OutFile);
L:=Length(Answer);
WriteLn(OutFile,L);
For i:=1 To L Do WriteLn(OutFile,Answer[i]);
Close(OutFile);
End { WriteOut };

Begin { Program }
ReadInput;
ComputeFact;
Generate(T);
Compose(T, Answer);
WriteOut;
End.

{ Scientific Committee IOI'96 }
mmmcd 2005-12-09
  • 打赏
  • 举报
回复

Program Magic;
Const
Size=8; { Size of the sheet }
M =40320; { =Size! }
Type
Trans =Array[1..Size] Of 1..Size;
Config=Array[1..Size] Of 1..Size;
Const
BT :Array['A'..'C'] Of Trans=((8,7,6,5,4,3,2,1), { basic transformations }
(4,1,2,3,6,7,8,5),
(1,7,2,4,5,3,6,8));
BT_1:Array['A'..'C'] Of Trans=((8,7,6,5,4,3,2,1), { inverses of the basic }
(2,3,4,1,8,5,6,7), { transformations }
(1,3,6,4,5,7,2,8));
Ini :Config=(1,2,3,4,5,6,7,8); { the initial configuration }
Var
T :Config; { the target configuration }
Answer:String; { the solution sequence of basic transformations }
Fact :Array[0..Size] Of Longint; { array of factorial values }
Last :Array[0..M] Of Char;
{ Last[Rank(T)] is the last character of a sequence of basic }
{ transformations that transforms the initial configuration to T. }
{ If Last[Rank(T)]=' ' then T has not been generated. }

Procedure ReadInput;
{ Global output variable: T }
Var InFile:Text;
i:Word;
Begin
Assign(InFile,'input.txt'); Reset(Infile);
For i:=1 To Size Do Read(Infile,T[i]);
Close(Infile);
End { ReadInput };

Procedure ComputeFact;
{ Computes the factorial values }
Var i:Word;
Begin
Fact[1]:=1;Fact[0]:=1;
For i:=2 To Size Do
Fact[i]:=i*Fact[i-1];
End;

Function Rank(Const P:Config): Word;
{ Rank(P) is the number of permutations that precedes P }
{ according to the lexicographic ordering. }
{ Global input variables: Size, Fact }
Var Res,l,i,j:Word;
Begin
Res:=0;
For i:=1 To Size Do Begin
l:=0; { l is the number of elements of P in positions }
{ 1..i-1 that are less than P[j] }
For j:=1 To i-1 Do
If P[j]<P[i] Then Inc(l);
{ Keeping fixed the first i-1 elements of P there can be (P[i]-1-l) }
{ numbers that are less than P[i] in position i in permutations. }
{ The number of permutations Q such that the first i-1 elements }
{ are the same as in P but Q precedes P in the lexicographic }
{ ordering is (P[i]-1-l)*Fact[Size-i]. }
Res:=Res+(P[i]-1-l)*Fact[Size-i];
End { For };
Rank:=Res;
End { Rank };

Procedure Apply(Const T:Config; X:Char; Var R:Config);
{ R is obtained by applying the basic transformation X }
{ to the configuration T }
Var i:Word;
Begin
For i:=1 To Size Do R[i]:=T[BT[X][i]];
End { Apply };

Procedure Apply_1(Const T:Config; X:Char; Var R:Config);
{ R is obtained by applying the inverse of the basic }
{ transformation X to the configuration T }
Var i:Word;
Begin
For i:=1 To Size Do R[i]:=T[BT_1[X][i]];
End {Apply_1};

Function Equal(Const R,T:Config): Boolean;
{ Checks equality of the configurations R and T }
Var i:Word;
Begin
i:=1;
While (i<=Size) And (R[i]=T[i]) Do Inc(i);
Equal:= i>Size;
End { Equal };

Procedure Generate(Const T: Config);
{ Generates a sequence of basic transformations that transforms the }
{ initial configuration to T. Last[Rank(T)] will be the last element of }
{ the sequence. }

{ Global input-output variable: Last }
Const
Qs=7000; { Queue size }
Var
Queue:Array[0..Qs-1] Of Config;
NotFound:Boolean;
Head,Tail:Word; { head and tail of the queue }
R,S: Config;
X: Char;

Procedure InitGener;
Var i:Word;
Begin
For i:=0 To M Do Last[i]:=' '; { initialize }
Last[0]:='.'; { 0=Rank(Ini), sentinel }
End;

Procedure InitQueue;
{ initialize the queue }
Begin
Head:=0; Tail:=1;
Queue[0]:=Ini; { put Ini into the queue }
End { InitQueue} ;

Procedure Enqueue(Const Q:Config);
Begin
Queue[Tail]:=Q;
Inc(Tail); If Tail=Qs Then Tail:=0;
End { Enqueue };

Procedure Dequeue(Var Q:Config);
Begin
Q:=Queue[Head];
Inc(Head); If Head=Qs Then Head:=0;
End { Dequeue };

Function NotMember(Const Q:Config; X:Char):Boolean;
{ Checks membership of Q in the set of generated configurations. }
{ If it is not generated then marks it as generated by setting the value }
{ of Last[Rank(Q)] to X. }
{ Global input-output variable: Last }
Var RankQ:Word;
Begin
RankQ:=Rank(Q);
If Last[RankQ]=' ' Then Begin
NotMember:=True;
Last[RankQ]:=X;
End Else
NotMember:=False;
End { NotMember };

Begin { Generate }
InitGener;
InitQueue;
NotFound:=True;
While NotFound Do Begin
Dequeue(R);
For X:='A' To 'C' Do Begin { apply all basic }
Apply(R, X, S); { transformations to R }
If NotMember(S,X) Then Begin { S is a new configuration }
If Equal(T,S) Then Begin { T=R*C decomposition found }
NotFound:= False;
Break; { exit the loop }
End;
Enqueue(S);
End { If new tr. };
End { For j };
End { While };
End { Generate };

Procedure Compose(Const T: Config; Var S:String);
{ Composes the sequence of basic transformations from the array Last }
{ following the link provided by the inverse transformation. }
{ Global input variable: Last }
Var
RankQ:Word; X:Char;
P,Q : Config;
Begin
Q:=T;
RankQ:=Rank(Q);
S:='';
While RankQ <> 0 Do Begin { while Q<>Ini }
X:=Last[RankQ];
S:=X+S; { append X to the left end of S }
Apply_1(Q,X,P); { Apply the inverse of X to Q }
Q:=P; { link to backward }
RankQ:=Rank(Q);
End { While };
End { Compose };

Procedure WriteOut;
{ Global input variable: Answer }
Var OutFile:Text;
L,i:Word;
Begin
Assign(OutFile,'output.txt'); Rewrite(OutFile);
L:=Length(Answer);
WriteLn(OutFile,L);
For i:=1 To L Do WriteLn(OutFile,Answer[i]);
Close(OutFile);
End { WriteOut };

Begin { Program }
ReadInput;
ComputeFact;
Generate(T);
Compose(T, Answer);
WriteOut;
End.

{ Scientific Committee IOI'96 }
mmmcd 2005-12-09
  • 打赏
  • 举报
回复
{
Solution of task MAGIC
-------- -- ---- -----

The following algorithm written in pseudocode generates all configurations
that can be obtained by applying a sequence of basic transformations to
the initial configuration.

Make the set Generated empty;
Make the set Disp empty;
Include the configuration Ini in Disp;
While Disp is not empty Do Begin
take an element P out of Disp;
for all basic transformation C Do Begin
let Q be the configuration obtained by applying C to P;
If Q is not in the set Generated Then Begin
include Q in the set Generated;
include Q in the set Disp;
End
End
End;

We can stop searching if the configuration Q is the target.
Let us first investigate the implementation of the operations on the set
Generated.
The number of all configurations is 8!=40320. It is too large to store the
configurations in an array. We can overcome this problem by using an
bijective function Rank that maps a configuration into a number in the range
0..8!-1. We can obtain such function by defining Rank(Q) as the number of
configurations that precedes Q according to the lexicographic ordering of the
permutations of the numbers 1..8.

Let us observe that each basic transformation C has a unique inverse in the
sense that for any configuration Q if C transforms Q to P then its inverse
transforms P to Q and conversely, if the inverse of C transforms P to Q then
C transforms Q to P. The inverses of the basic transformations are:
A: A itself,
B: single left circular shifting,
C: single anti-clockwise rotation of the middle four squares.

If the configuration Q is obtained in the algorithm by applying the basic
transformation C to P then there is a sequence of basic transformations that
transforms the initial configuration to Q whose last element is C. If we know
Q and C then we can compute P by applying the inverse of C to Q.
Consider the array Last: Array[0..8!-1] Of Char. We use the array Last for
two purposes. Last[Rank(Q)]=' ' iff the configuration Q has not been
generated. If Q is obtained during the generation by applying C to a
configuration P then Last[Rank(Q)] is set to C. Following the link provided
by the inverse transformation we can compose the whole sequence of basic
transformations for the target configuration T.

S:=''; (* string S is set to empty *)
While T <> Ini Do Begin
X:=Last[Rank(T)];
S:=X+S; (* append X to the left end of S *)
Apply_1(T,X,P); (* Apply the inverse of X to T *)
T:=P; (* link to backward *)
End (* While *);

We implement the dispenser Disp as a queue, i.e. by first-in first-out policy;
items come out in the order of their insertion.
A simple experiment will show that the maximal length of the sequences
produced by the algorithm is 22.

The queue implementation of the dispenser provides optimal solution in the
sense that for each configuration T the algorithm produces the shortest
sequence of basic transformations.
We prove by induction on the length of the optimal solution.
Let us denote by l(T) the length of the sequence generated by the algorithm
for configuration T.

Suppose that during the execution of the algorithm the queue contains the
configurations T1,...,Tk where T1 is the head. Then the
following two conditions hold:
1) l(T1)<=...<=l(Tk)
2) l(Tk)<=l(T1)+1
The proof is by induction on the number of queue operations.
Initially the statement holds because only the initial configuration
is in the queue and l(Ini)=0. If the head T1 is dequeued, then the new head is
T2. But then we have l(Tk)<=l(T1)+1<=l(T2)+1, and the remaining inequalities
are unaffected. Consider the case when T1 is dequeued and the new
configuration Q which is obtained by applying C to T1 is enqueued.
Then l(Q)=l(T1)+1, therefore the inequalities
l(Tk)<=l(T1)+1=l(Q) and l(Q)=l(T1)+1<=l(T2)+1
hold by 1) and 2).

It follows from the previous statement that if the configurations inserted
into the queue over the course of the algorithm in the order T1,...,Tn
then l(T1)<=...<=l(Tn).

Let T(k) denote the set of all configurations Q that the minimal length of the
sequence of basic transformations that transform Ini to Q is k. The proof of
the optimality of the algorithm follows by induction on k.

The elements of T(1) are those configurations that can be obtained by applying
the basic transformations to Ini. The statement obviously holds for k=1.
Assume that the statement holds for all l<k. Let Q be a configuration in T(k).
Then there is a configuration P in T(k-1) and a basic transformation C such
that Q can be obtained by applying C to P. By the inductive hypotheses,
l(P)=k-1. P was inserted into the queue when it was generated by the algorithm.
Consider the time when the algorithm dequeues P from the queue and checks
whether Q is already generated. If Q is new then the algorithm
generates Q and hence l(Q)=l(P)+1=k. If Q was already generated then
l(Q)<=l(P)=k-1 by the monotonicity property, which is a contradiction.

}
mmmcd 2005-12-09
  • 打赏
  • 举报
回复
{
Solution of task MAGIC
-------- -- ---- -----

The following algorithm written in pseudocode generates all configurations
that can be obtained by applying a sequence of basic transformations to
the initial configuration.

Make the set Generated empty;
Make the set Disp empty;
Include the configuration Ini in Disp;
While Disp is not empty Do Begin
take an element P out of Disp;
for all basic transformation C Do Begin
let Q be the configuration obtained by applying C to P;
If Q is not in the set Generated Then Begin
include Q in the set Generated;
include Q in the set Disp;
End
End
End;

We can stop searching if the configuration Q is the target.
Let us first investigate the implementation of the operations on the set
Generated.
The number of all configurations is 8!=40320. It is too large to store the
configurations in an array. We can overcome this problem by using an
bijective function Rank that maps a configuration into a number in the range
0..8!-1. We can obtain such function by defining Rank(Q) as the number of
configurations that precedes Q according to the lexicographic ordering of the
permutations of the numbers 1..8.

Let us observe that each basic transformation C has a unique inverse in the
sense that for any configuration Q if C transforms Q to P then its inverse
transforms P to Q and conversely, if the inverse of C transforms P to Q then
C transforms Q to P. The inverses of the basic transformations are:
A: A itself,
B: single left circular shifting,
C: single anti-clockwise rotation of the middle four squares.

If the configuration Q is obtained in the algorithm by applying the basic
transformation C to P then there is a sequence of basic transformations that
transforms the initial configuration to Q whose last element is C. If we know
Q and C then we can compute P by applying the inverse of C to Q.
Consider the array Last: Array[0..8!-1] Of Char. We use the array Last for
two purposes. Last[Rank(Q)]=' ' iff the configuration Q has not been
generated. If Q is obtained during the generation by applying C to a
configuration P then Last[Rank(Q)] is set to C. Following the link provided
by the inverse transformation we can compose the whole sequence of basic
transformations for the target configuration T.

S:=''; (* string S is set to empty *)
While T <> Ini Do Begin
X:=Last[Rank(T)];
S:=X+S; (* append X to the left end of S *)
Apply_1(T,X,P); (* Apply the inverse of X to T *)
T:=P; (* link to backward *)
End (* While *);

We implement the dispenser Disp as a queue, i.e. by first-in first-out policy;
items come out in the order of their insertion.
A simple experiment will show that the maximal length of the sequences
produced by the algorithm is 22.

The queue implementation of the dispenser provides optimal solution in the
sense that for each configuration T the algorithm produces the shortest
sequence of basic transformations.
We prove by induction on the length of the optimal solution.
Let us denote by l(T) the length of the sequence generated by the algorithm
for configuration T.

Suppose that during the execution of the algorithm the queue contains the
configurations T1,...,Tk where T1 is the head. Then the
following two conditions hold:
1) l(T1)<=...<=l(Tk)
2) l(Tk)<=l(T1)+1
The proof is by induction on the number of queue operations.
Initially the statement holds because only the initial configuration
is in the queue and l(Ini)=0. If the head T1 is dequeued, then the new head is
T2. But then we have l(Tk)<=l(T1)+1<=l(T2)+1, and the remaining inequalities
are unaffected. Consider the case when T1 is dequeued and the new
configuration Q which is obtained by applying C to T1 is enqueued.
Then l(Q)=l(T1)+1, therefore the inequalities
l(Tk)<=l(T1)+1=l(Q) and l(Q)=l(T1)+1<=l(T2)+1
hold by 1) and 2).

It follows from the previous statement that if the configurations inserted
into the queue over the course of the algorithm in the order T1,...,Tn
then l(T1)<=...<=l(Tn).

Let T(k) denote the set of all configurations Q that the minimal length of the
sequence of basic transformations that transform Ini to Q is k. The proof of
the optimality of the algorithm follows by induction on k.

The elements of T(1) are those configurations that can be obtained by applying
the basic transformations to Ini. The statement obviously holds for k=1.
Assume that the statement holds for all l<k. Let Q be a configuration in T(k).
Then there is a configuration P in T(k-1) and a basic transformation C such
that Q can be obtained by applying C to P. By the inductive hypotheses,
l(P)=k-1. P was inserted into the queue when it was generated by the algorithm.
Consider the time when the algorithm dequeues P from the queue and checks
whether Q is already generated. If Q is new then the algorithm
generates Q and hence l(Q)=l(P)+1=k. If Q was already generated then
l(Q)<=l(P)=k-1 by the monotonicity property, which is a contradiction.

}

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧