2017.4.2测试T4 game 搜索

第四题(50分)(每个测试数据2分)

提交文件:game.exe

输入文件:game.in

输出文件:game.out

题目描述

下面介绍一个小游戏:

在一个M×N的板上,有部分格子被标记为障碍(例如上图黑色标示的格子)。你任选一个空白格子放置一个小球(如上图灰点所示),并选择小球滚动的方向(上,下,左,右),小球将在板上一直滚动直至它碰到障碍,或板的边界,或它之前经过的格子。如果小球遇到以上情况之一将停下,你可以给它另选滚动的方向,然后小球将以同样的方式前进。如果小球在四个方向上都无法继续滚动,游戏结束,这时假如小球的轨迹覆盖板上所有的空白格子,你将获胜。上图展示的轨迹就是一个仅用10步获胜的例子。

你的任务是对给定板子,计算赢得游戏所需的最少步数。

输入格式(map.in):

输入的第一行是用空格分隔的两个正整数m和n(m,n<=30),分别板子的高和宽。接下来的m行,每行有n个字符,含义如下:

‘.’:该格是空白格子;

‘*’:该格被标记为障碍。

我们保证板子不会全部被标记为障碍。

输出格式(map.out):

输出仅一个整数,表示计算赢得游戏所需的最少步数。假如无法取胜,则输出-1。

样例

game.in

game.out

5 5

**...

.....

....*

..*..

.....

10


题解:从每个可走的点搜索。剪枝:如果当前走的步数大于之前找到的答案最小值可以直接结束这个点

const
  maxn=40;
  fx:array[1..4,1..2]of longint=((-1,0),(1,0),(0,-1),(0,1));
  inf='game.in';
  ouf='game.out';
var
  a:array[0..maxn+1,0..maxn+1]of boolean;
  n,m,i,j,ans,sum:longint;

procedure init;
var
  i,j:longint;
  ch:char;
begin
  readln(m,n);
  fillchar(a,sizeof(a),true);
  for i:=1 to m do
  begin
    for j:=1 to n do
    begin
      read(ch);
      if ch='*' then
      begin
        inc(sum);
        a[i,j]:=false;
      end;
    end;
  readln;
  end;
  fillchar(a[0],sizeof(a[0]),false);
  fillchar(a[m+1],sizeof(a[m+1]),false);
  for i:=1 to m do
  begin
    a[i,0]:=false;
    a[i,n+1]:=false;
  end;
  ans:=maxlongint;
end;

procedure dfs(dep,x,y,tot:longint);
var
  i,px,py:longint;
begin
  if dep>=ans then exit;
  if tot=n*m-sum then
  begin
    if dep<ans then ans:=dep;
    exit;
  end;
  for i:=1 to 4 do
  begin
    px:=x;py:=y;
    while a[px+fx[i,1],py+fx[i,2]] do
    begin
      px:=px+fx[i,1];py:=py+fx[i,2];
      a[px,py]:=false;
    end;
    if (px<>x)or(py<>y)then
    begin
      dfs(dep+1,px,py,tot+abs(px-x)+abs(py-y));
      while (x<>px)or(y<>py) do
      begin
        a[px,py]:=true;
        px:=px-fx[i,1];py:=py-fx[i,2];
      end;
    end;
  end;
end;

begin
  assign(input,inf);reset(input);
  assign(output,ouf);rewrite(output);
  init;
  for i:=1 to m do
    for j:=1 to n do
    if a[i,j] then
    begin
      a[i,j]:=false;
      dfs(0,i,j,1);
      a[i,j]:=true;
    end;
  if ans=maxlongint then ans:=-1;
  writeln(ans);
  close(input);close(output);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值