奶牛们在被划分成N行M列(2 <= N <= 100; 2 <= M <= 100)的草地上游走,试图找到整块草地中最美味的牧草。Farmer John在某个时刻看见贝茜在位置 (R1, C1),恰好T (0 < T <= 15)秒后,FJ又在位置(R2, C2)与贝茜撞了正着。 FJ并不知道在这T秒内贝茜是否曾经到过(R2, C2),他能确定的只是,现在贝茜在那里。 设S为奶牛在T秒内从(R1, C1)走到(R2, C2)所能选择的路径总数,FJ希望有一个程序来帮他计算这个值。每一秒内,奶牛会水平或垂直地移动1单位距离(奶牛总是在移动,不会在某秒内停在它上一 秒所在的点)。草地上的某些地方有树,自然,奶牛不能走到树所在的位置,也不会走出草地。 现在你拿到了一张整块草地的地形图,其中’.’表示平坦的草地,’*’表示挡路的树。你的任务是计算出,一头在T秒内从(R1, C1)移动到(R2, C2)的奶牛可能经过的路径有哪些。
双向广搜
从起点出发走T/2步,记录每个格子到达次数a[i][j]
从终点出发走T-T/2步,记录每个格子到达次数b[i][j]
所有格子的a[i][j]*b[i][j]就是答案
复杂度4^(T/2)+n*m
此题如果T更大,可以用dp解决,做到O(n*m*T)或O((n*m)^3*logT)
#include<iostream>
using namespace std;
int n,t,m;
int hz[5]={0,0,0,1,-1};
int zz[5]={0,1,-1,0,0};
int a[101][101],b[101][101];char tmp[101][101];
int dfs(int bs,int h,int z,int s[101][101],int tt)
{ if (bs>tt)
{ s[h][z]++;
return 0;
}
for (int i=1;i<=4;++i)
{ if (h+hz[i]>=1&&h+hz[i]<=n&&z+zz[i]>=1&&z+zz[i]<=m)
if (tmp[h+hz[i]][z+zz[i]]!='*')
{
dfs(bs+1,h+hz[i],z+zz[i],s,tt);
}
}
}
int main()
{
int x1,y1,x2,y2;
cin>>n>>m>>t;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
cin>>tmp[i][j];
cin>>x1>>y1>>x2>>y2;
int t1=t/2;
int t2=t-t1;
dfs(1,x1,y1,a,t1);
dfs(1,x2,y2,b,t2);
int ans=0;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
ans+=a[i][j]*b[i][j];
cout<<ans;
}