洛谷 P1535【游荡的奶牛】
题目描述
Searching for the very best grass, the cows are travelling about the pasture which is represented as a grid with N rows and M columns (2 <= N <= 100; 2 <= M <= 100). Keen observer Farmer John has recorded Bessie's position as (R1, C1) at a certain time and then as (R2, C2) exactly T (0 < T <= 15) seconds later. He's not sure if she passed through (R2, C2) before T seconds, but he knows she is there at time T.
FJ wants a program that uses this information to calculate an integer S that is the number of ways a cow can go from (R1, C1) to (R2, C2) exactly in T seconds. Every second, a cow can travel from any position to a vertically or horizontally neighboring position in the pasture each second (no resting for the cows). Of course, the pasture has trees through which no cow can travel.
Given a map with '.'s for open pasture space and '*' for trees, calculate the number of possible ways to travel from (R1, C1) to (R2, C2) in T seconds.
奶牛们在被划分成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)的奶牛 可能经过的路径有哪些。
输入输出格式
输入格式
第1 行: 3 个用空格隔开的整数:N,M,T 。 第2..N+1 行: 第i+1 行为M 个连续的字符,描述了草地第i 行各点的情况,保证字符是'.'和'*'中的一个。 第N+2 行: 4 个用空格隔开的整数:R1,C1,R2,C2 。
输出格式
第1 行: 输出S,含义如题中所述。
输入输出样例
输入样例1
4 5 6 ...*. ...*. ..... ..... 1 3 1 5
输出样例1
1
解题思路
首先呢,这道题我就是爆搜,然后因为这个不用求最短时间,所以不用打标记,所以方案很多,所以就光荣的MLE了。然后自己想了想,既然有方案数,是不是可以记忆化搜索呢?果然,我们开一个三维的dp数组,代表第t秒到达x,y的方案,如果这个点没被找过,那方案数就是拓展它的点的方案数,但是如果被找过了,我们就要加上现在拓展它的点的方案数,这样就避免很多不必要的运算。
题解
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,T,sx,sy,ex,ey,ans; 4 char mp[101][101];//存图的 5 int dp[101][101][101];//记忆化必备 6 struct node{ 7 int xx;//坐标和步数 8 int yy; 9 int t; 10 node(){} 11 node(int xxx,int yyy,int tt)//构造函数 12 { 13 xx=xxx; 14 yy=yyy; 15 t=tt; 16 } 17 }; 18 queue<node> q;//队列 19 int dir[4][2]={0,1,0,-1,1,0,-1,0};//四方向拓展 20 void dfs(int tx,int ty) 21 { 22 q.push(node(tx,ty,0));//进去 23 while(!q.empty()) 24 { 25 node head=q.front();//取队首 26 q.pop();//踢出 27 if(head.t==T)//如果步数达到 28 { 29 continue;//进行下一次操作 30 } 31 else for(int i=0;i<4;i++)//四方向拓展 32 { 33 int X=head.xx+dir[i][0]; 34 int Y=head.yy+dir[i][1]; 35 if(dp[X][Y][head.t+1])//如果被找过 36 { 37 dp[X][Y][head.t+1]+=dp[head.xx][head.yy][head.t];//加上它的方案数就行了 38 } 39 else if(mp[X][Y]!='*'&&X>=1&&X<=n&&Y>=1&&Y<=m)//能走并且没越界 40 { 41 dp[X][Y][head.t+1]+=dp[head.xx][head.yy][head.t];//记录方案数 42 q.push(node(X,Y,head.t+1));//加入队列 43 } 44 } 45 } 46 cout<<dp[ex][ey][T];//输出 47 } 48 int main() 49 { 50 cin>>n>>m>>T; 51 for(int i=1;i<=n;i++) 52 { 53 for(int j=1;j<=m;j++) 54 { 55 cin>>mp[i][j]; 56 } 57 } 58 cin>>sx>>sy>>ex>>ey; 59 dp[sx][sy][0]=1;//初始方案数为1 60 dfs(sx,sy); 61 }