通过交换相邻数字对填充数字的加扰二维数组进行排序


9

大小为n×n的二维数组由n * n个数字填充,从数字1开始。这些数字将按行升序排序;行的第一个数字必须大于上一行的最后一个数字(所有(1)中最小的数字将在[0,0]中)。这类似于15个难题

例如,这是大小为n = 3的排序数组。

1 2 3
4 5 6
7 8 9

输入项

输入是加扰的数组。它的大小最大为n =10。n= 3的示例:

4 2 3
1 8 5
7 9 6

输出量

输出排序数组所需的交换列表。甲交换被定义如下:两个相邻的数字交换位置,水平或垂直; 不允许对角交换。

上面示例的示例输出:

  • 交换4和1
  • 交换8和5
  • 交换8和6
  • 交换9和8

所需的交换次数越少越好。计算时间必须可行。


这是另一个示例输入,其中n = 10:

41 88 35 34 76 44 66 36 58 28
6 71 24 89 1 49 9 14 74 2
80 31 95 62 81 63 5 40 29 39
17 86 47 59 67 18 42 61 53 100
73 30 43 12 99 51 54 68 98 85
13 46 57 96 70 20 82 97 22 8
10 69 50 65 83 32 93 45 78 92
56 16 27 55 84 15 38 19 75 72
33 11 94 48 4 79 87 90 25 37
77 26 3 52 60 64 91 21 23 7

如果我没记错的话,这大约需要1000-2000次交换。


这是难题,速度还是打高尔夫球?
Michael Klein

@MichaelKlein这是一个难题。
JCarter '16

得分了吗?需要处理什么范围?
Michael Klein

1
@steveverrill恐怕要在少于100个交换(甚至1000个交换)中解决n = 10的例子是完全不可能的,但是请证明我错了。不过,掉期数仍然是获胜的标准(尽管计算必须可行!),谁提出了交换数最少的解决方案的人就是赢家。
JCarter

1
@JCarter我想你的意思是只能交换相邻的数字?
quintopia '16

Answers:


3

Mathematica,不打高尔夫球

towards[a_,b_]:={a,a+If[#==0,{0,Sign@Last[b-a]},{#,0}]&@Sign@First[b-a]};
f[m_]:=Block[{m2=Map[QuotientRemainder[#-1,10]+1&,m,{2}]},
  Rule@@@Apply[10(#1-1)+#2&,#,{2}]&@
    Reap[Table[
      m2=NestWhile[
        Function[{x},x/.(Sow[#];Thread[#->Reverse@#])&[x[[##]]&@@@towards[First@Position[x,i,{2}],i]]]
        ,m2,#~Extract~i!=i&];
      ,{i,Reverse/@Tuples[Range[10],2]}];][[2,1]]]

说明

该算法类似于“气泡排序”。将这100个数字一一正确地排序1, 11, 21, ..., 91; 2, ..., 92; ...; 10, ..., 100。它们首先向上/向下移动到正确的行,然后向左移动到正确的列。

函数towards给出两个位置进行交换。例如,如果{5,2}移到{1,1},则towards[{5,2},{1,1}]放弃{{5,2},{5,1}}(向上移动);并 towards[{5,1},{1,1}]给出{{5,1},{4,1}}(向左移动)。


结果

对于测试用例,交换的总数为558。前几个交换是,

{1->76,1->34,1->35,1->88,1->41,11->16,11->69,11->46, ...

对于随机配置,交换总数为558.5±28.3(1σ)。

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.