马拦过河卒

 

【问题描述】

棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。

棋盘用坐标表示,A(0, 0)、B(n, m)(n, m为不超过15的整数),同样马的位置坐标是需要给出的。现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

【输入】

一行四个数据,分别表示B点坐标和马的坐标。

【输出】

一个数据,表示所有的路径条数。

【样例】

knight.in 

6 6 3 3

knight.out

 6

///

      这道题,是简单的回溯,卒只能向下或向右走,所以可以回溯,也可以用递推,但如果可以向上、下、左、右四个方向走时,就只能用回溯了。。。。。。。。

回溯:

var n,m,x,y:byte;ans:longint;
    v:array[0..15,0..15]of boolean;
procedure init;
  begin
    fillchar(v,sizeof(v),true);
    readln(n,m,x,y);
    v[x,y]:=false;
    v[x+1,y+2]:=false;v[x-1,y+2]:=false;
    v[x+1,y-2]:=false;v[x-1,y-2]:=false;
    v[x+2,y+1]:=false;v[x-2,y+1]:=false;
    v[x+2,y-1]:=false;v[x-2,y-1]:=false;
  end;
procedure dfs(x0,y0:byte);
  begin
    if (x0=n)and(y0=m) then
       inc(ans);//若这里用begin inc(ans);exit;end;  “12 12 5 6”这个点就会超时
    if (x0+1<=n)and(v[x0+1,y0]) then dfs(x0+1,y0);
    if (y0+1<=m)and(v[x0,y0+1]) then dfs(x0,y0+1);    
  end;
procedure main;
    begin
      ans:=0;
      dfs(0,0);
      writeln(ans);
    end;
begin
 assign(input,'knight.in');reset(input);
 assign(output,'knight.out');rewrite(output);
  init;
  main;
 close(input);close(output);
end.

递推:

var a:array[-1..15,-1..15]of longint;
    v:array[0..15,0..15]of boolean;
    n,m,x,y:byte;
procedure init;
 var i:byte;
  begin
    readln(n,m,x,y);
    fillchar(v,sizeof(v),true);
    fillchar(a,sizeof(a),0);
    v[x,y]:=false;
    v[x+1,y+2]:=false;v[x-1,y+2]:=false;
    v[x+1,y-2]:=false;v[x-1,y-2]:=false;
    v[x+2,y+1]:=false;v[x-2,y+1]:=false;
    v[x+2,y-1]:=false;v[x-2,y-1]:=false;
    if v[0,0] then a[0,0]:=1;
    for i:=1 to n do if v[i,0] then a[i,0]:=a[i-1,0]+a[i,0];
    for i:=1 to m do if v[0,i] then a[0,i]:=a[0,i-1]+a[0,i];
  end;
procedure main;
  var i,j:byte;
    begin
      for i:=1 to n do
        for j:=1 to m do
          if v[i,j] then a[i,j]:=a[i,j]+a[i-1,j]+a[i,j-1];
      writeln(a[n,m]);
    end;
begin
 assign(input,'knight.in');reset(input);
 assign(output,'knight.out');rewrite(output);
  init;
  main;
 close(input);close(output);
end.



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值