【问题描述】
棋盘上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.