魔术数字游戏

 

魔术数字游戏

源程序名            magic.???(pas, c, cpp)

可执行文件名        magic.exe

输入文件名          magic.in

输出文件名          magic.out

【问题描述】

           填数字方格的游戏有很多种变化,如下图所示的4×4方格中,我们要选择从数字1到16来填满这十六个格子(Aij,其中i=1..4,j=1..4)。为了让游戏更有挑战性,我们要求下列六项中的每一项所指定的四个格子,其数字累加的和必须为34:

     1.四个角落上的数字,即A11+A14+A41+A44=34。

    2.每个角落上的2×2方格中的数字,例如左上角:A11+A12+A21+A22=34。

    3.最中间的2×2方格中的数字,即A22+A23+A32+A33=34。

    4.每条水平线上四个格子中的数字,即Ai1+Ai2+Ai3+Ai4=34,其中i=1..4。

    5.每条垂直线上四个格子中的数字,即A1j+A2j+A3j+A4j=34,其中j=1..4。

    6两条对角线上四个格子中的数字,例如左上角到右下角:A11+A22+A33+A44=34。

右上角到左下角:A14+A23+A32+A41=34

A11

A12

A13

A14

A21

A22

A23

A24

A31

A32

A33

A34

A41

A42

A43

A44

【输入】

       输入文件会指定把数字1先固定在某一格内。输入的文件只有一行包含两个正数据I和J,表示第1行和第J列的格子放数字1。剩下的十五个格子,请按照前述六项条件用数字2到16来填满。

【输出】

       把全部的正确解答用每4行一组写到输出文件,每行四个数,相邻两数之间用一个空格隔开。两组答案之间,要以一个空白行相间,并且依序排好。排序的方式,是先从第一行的数字开始比较,每一行数字,由最左边的数字开始比,数字较小的解答必须先输出到文件中。

【样例】

 magic.in   

  1 1                                        

magic.out

1 4 13 16

14 15 2 3

8 5 12 9

11 10 7 6

 

1 4 13 16

14 15 2 3

12 9 8 5

7 6 11 10{样例输出没写完}

====================================

初始想法:

开5个hash

判断是否>34

若>34则剪掉...

但是这个想法有一个根本上的问题。

就是若前面的那些小于34的话后面就有很多冗余操作

所以初始想法就是错误的...

---------------------------------------------------------------------

正确做法:

直接搜到关键节点的时候直接判断是否=34

若<>34则剪掉。

-----------------------------------------------------------------------

所以在做这类似的有剪枝的search题的时候

应该先考虑剪枝的正确性。在考虑剪枝如何实现。

===========================================

var
  f:array[2..16]of boolean;
  //f_bool:array[1..5,0..4]of longint;
  //z:array[1..16,1..5,0..4]of longint;
  z:array[1..16]of longint;
  x,y,v_1:longint;
procedure init;
begin
  assign(input,'magic.in');
  assign(output,'magic.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure dfs(t:longint);
var
  i:longint;
  j:longint;
  flag:boolean;
begin
  if t>16 then
    begin
      for i:=1 to 16 do
        begin
          write(z[i],' ');
          if i mod 4=0 then writeln;
        end;
      writeln;
      exit;
    end;

  if t=v_1 then
    begin
      flag:=false;
      if t=4 then if z[1]+z[2]+z[3]+z[4]<>34 then flag:=true;
      if t=6 then if z[1]+z[2]+z[5]+z[6]<>34 then flag:=true;
      if t=8 then
        begin
          if z[5]+z[6]+z[7]+z[8]<>34 then flag:=true;
          if z[7]+z[8]+z[3]+z[4]<>34 then flag:=true;
        end;
      if t=11 then if z[10]+z[11]+z[6]+z[7]<>34 then flag:=true;
      if t=13 then
        begin
          if z[1]+z[5]+z[9]+z[13]<>34 then flag:=true;
          if z[4]+z[7]+z[10]+z[13]<>34 then flag:=true;
        end;
      if t=14 then
        begin
          if z[9]+z[10]+z[11]+z[12]<>34 then flag:=true;
          if z[2]+z[6]+z[10]+z[14]<>34 then  flag:=true;
          if z[9]+z[10]+z[13]+z[14]<>34 then flag:=true;
        end;
      if t=15 then if z[3]+z[7]+z[11]+z[15]<>34 then flag:=true;
      if t=16 then
        begin
          if z[13]+z[14]+z[15]+z[16]<>34 then flag:=true;
          if z[4]+z[8]+z[12]+z[16]<>34 then flag:=true;
          if z[1]+z[4]+z[13]+z[16]<>34 then flag:=true;
          if z[11]+z[12]+z[15]+z[16]<>34 then flag:=true;
          if z[1]+z[6]+z[11]+z[16]<>34 then flag:=true;
        end;
      if not flag then dfs(t+1);
      exit;
    end;
  for i:=2 to 16 do
    if f[i] then
    begin
      f[i]:=false;
      z[t]:=i;
      
      if t=4 then
        begin
          if z[1]+z[2]+z[3]+z[4]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
        end;
      if t=6 then
        begin
          if z[1]+z[2]+z[5]+z[6]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
        end;
      if t=8 then
        begin
          if z[5]+z[6]+z[7]+z[8]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
          if z[7]+z[8]+z[3]+z[4]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
        end;
      if t=11 then
        begin
          if z[10]+z[11]+z[6]+z[7]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
        end;
      if t=13 then
        begin
          if z[1]+z[5]+z[9]+z[13]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
          if z[4]+z[7]+z[10]+z[13]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
        end;
      if t=14 then
        begin
          if z[9]+z[10]+z[11]+z[12]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
          if z[2]+z[6]+z[10]+z[14]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
          if z[9]+z[10]+z[13]+z[14]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
        end;
      if t=15 then
        begin
          if z[3]+z[7]+z[11]+z[15]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
        end;
      if t=16 then
        begin
          if z[13]+z[14]+z[15]+z[16]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
          if z[4]+z[8]+z[12]+z[16]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
          if z[1]+z[4]+z[13]+z[16]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
          if z[11]+z[12]+z[15]+z[16]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
          if z[1]+z[6]+z[11]+z[16]<>34 then
            begin
              f[i]:=true;
              continue;
            end;
        end;
      dfs(t+1);
      f[i]:=true;
    end;
end;

procedure main;
var
  i:longint;
begin
  readln(x,y);
  fillchar(f,sizeof(f),true);
  v_1:=(x-1)*4+y;
  z[v_1]:=1;
  dfs(1);
end;

begin
  init;
  main;
  terminate;
end.   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值