中国跳棋动作最长


12

中文跳棋中,一件作品可以通过跳到其他任何一件作品上或通过进行一系列这样的跳跃来移动。您的任务是找到可能的最长跳数序列​​。

输入值

121个零或一的序列,每个零代表一个在板上的位置。零表示该地点为空;一个表示该位置已被占用。位置从左到右列出;从上到下。例如,输入这种设置

1011110011000001000000000000000000000000100000000001000000000000000000000000000001000000000000000000000001000001100111111

说明:

最上面的位置被一块绿色占据,因此输入中的第一位是1。第二行有一个空位置,然后有一个占用位置,所以01接下来是。第三行已全部占用,因此111。第四行有两个空白和两个占用的空间(从左到右),所以0011。然后是下一行的五个0,一个1和七个0,依此类推。

就像在该设置中一样,有一个角指向上。板上可以有任意数量的部件(从1到121)。请注意,不同颜色的块表示方式不同。

输出量

合法跳的最大长度,使用板上的任何一块。您可能不能多次访问同一个地方(包括起点和终点)。但是,您可能会多次跳过同一块。如果没有合法的跃点,则输出0。不要考虑是否存在合法的非跳跃动作。

例如,上述设置的输出为3

输入和输出可以通过stdin和stdout,命令行参数,函数调用或任何类似方法来完成。

测试用例

输入:

0100000010000000000000000100000000000000000000000000000001010010000000000000000000000101000000000000000000100000000100001

输出:(0没有两个相邻的部分)


输入:

0000000000111100000000011100000000011000000000100000000000000000000000000000000000000000000000000000000000000000000000000

输出:(1在左上角为一名玩家设置的初始设置)


我和我的大姨妈一起玩。我们俩都还不错。这是一个有趣的挑战。
cjfaure

1
也许您应该指定更多有关如何存储输入/哪些位转到何处的信息。
TheDoctor 2014年

您可以“跳过去”哪些作品?我和我妈妈的演奏方式是,只要没有障碍物,您就可以沿6个方向之一跳越任意距离(到您跳过的那部分的相反点)。跳的路径。其他人则认为您只能跳过相邻的曲目。
乔Z。2014年

1
@TheDoctor我添加了更详细的解释。
Ypnypn

您能否澄清一个细节:我可以两次担任同一个职位吗?我以为我不能无限循环,但是如果我可以碰到一个从左到右移动的位置,然后再打到它又从上到下移动到右下的位置,那么它将为您带来无限可能。
德文·帕森斯

Answers:


1

Perl中,345 322

编辑:打高尔夫球,略。

可以使用更多的测试用例,但是现在看来它可以工作。如有必要,我将在以后添加评论。带有换行符和缩进以提高可读性:

$_=<>;
$s=2x185;
substr$s,(4,22,unpack'C5(A3)*','(:H[n129148166184202220243262281300')[$i++],0,$_ 
    for unpack A.join A,1..4,13,12,11,10,9..13,4,3,2,1;
$_=$s;
sub f{
    my(@a,%h)=@_;
    $h{$_}++&&return for@a;
    $-+=$#a>$-;
    $s=~/^.{$a[0]}$_/&&f($+[1],@a)
        for map{("(?=.{$_}1.{$_}(0))","(?<=(0).{$_}1.{$_}.)")}0,17,18
}
f$+[0]while/1/g;
print$-

我添加了一些测试用例。
Ypnypn

那些工作正常,但它们太容易了:-)。
user2846289 2014年

2

C,262 260

合并的代码(调试代码和不必要的空格已删除。从通过stdin的输入更改为通过命令行的输入,并利用了在此处声明变量i的机会。最新编辑:将代码移入for循环括号中以保存两个分号。)

t[420],j,l,x,y;f(p,d){int z,q,k;for(k=6;k--;t[q]&!t[p+z]?t[q]=0,f(q,d+1),t[q]=1:0)z="AST?-,"[k]-64,q=p+z*2;l=d>l?d:l;}main(int i,char**s){for(i=840;i--;x>3&y>5&x+y<23|x<13&y<15&x+y>13?i>420?t[i-420]=49-s[1][j++]:t[i]||f(i,0):0)x=i%20,y=i/20%21;printf("%d",l);}

说明

这依赖于一个看起来像这样的20x21板,在程序启动时最初用零填充(此ASCII文字是由程序的修改版本生成的,并且随着i循环向下计数,右下角为零):

....................
....................
...............#....
..............##....
.............###....
............####....
.......#############
.......############.
.......###########..
.......##########...
.......#########....
......##########....
.....###########....
....############....
...#############....
.......####.........
.......###..........
.......##...........
.......#............
....................
....................

循环i遍历此板两次,使用x和y来计算正方形是否真正属于棋盘格(这需要在x和y中有6个独立的不等式。)

如果是这样,则它会在第一回合填充正方形,将0(虚假)代表1(占用),将1(真实)代表0(空闲)。这种反转非常重要,因为所有越界正方形都已经包含0,这意味着它们类似于占用的正方形,并且很明显,无需特殊检查就可以将它们跳入。

第二次,如果正方形被占用(包含0),它将调用f搜索移动的函数。

f在表达式中编码的+/- 1(水平),+ /-20(垂直)和+/- 19(对角线)编码的6个可能方向上递归搜索"AST?-,"[k]-64。当找到命中时,它将在递归调用自身之前将该单元格设置为0(占用),然后在返回该函数时将其设置回1(空)。必须在递归调用之前更改单元格的值,以防止多次跳入该单元格。

非高尔夫代码

char s[999];                           //input string.
t[420],i,j,l,x,y;                      //t=board. i=board counter, j=input counter. l=length of longest hop found so far.

f(p,d){                                //p=position, d= recursion depth.
  //printf("%d,%d ",p,d);              //debug code: uncomment to show the nodes visited.
  int k,z,q;                           //k=counter,z=displacement,q=destination
  for(k=6;k--;)                        //for each direction
    z="AST?-,"[k]-64,                  //z=direction
    q=p+z*2,                           //q=destination cell
    t[q]&!t[p+z]?                      //if destination cell is empty (and not out of bounds) and intervening cell is full
      t[q]=0,f(q,d+1),t[q]=1           //mark destination cell as full, recurse, then mark it as empty again.
      :0;
  l=d>l?d:l;                           //if d exceeds the max recorded recursion depth, update l
}

main(){
  gets(s);                             //get input
  for(i=840;i--;)                      //cycle twice through t
    x=i%20,                            //get x
    y=i/20%21,                         //and y coordinates
    x>3&y>5&x+y<23|x<13&y<15&x+y>13?   //if they are in the bounds of the board
      i>420?
        t[i-420]=49-s[j++]             //first time through the array put 0 for a 1 and a 1 for a 0 ('1'=ASCII49)
        :t[i]||f(i,0)                  //second time, if t[i]=0,call f(). 
       //,puts("")                     //puts() formats debug output to 1 line per in-bounds cell of the board
      :0;
  printf("%d",l);                      //print output
}
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.