搜索
不知道为什么没有人写bfs
觉得挺像是标准个bfs的
状态
因为要统计次数,不能简单地跳过一个被经过的点
这样的话,状态量会爆炸
采用记忆化
设dp[i][j][k]表示在第k分钟到达点(i,j)的方案数
以地点+时间作为状态
避免同一状态被反复拓展
这样,状态量将减少至最多100*100*15
转移
这就比较显然了
对于将被拓展的状态,在计数时加上当前状态的方案数
如果这个状态曾被拓展,就不要别的操作了
否则,将这一状态入队,预备拓展其他状态
代码是这样的:
#include<iostream> #include<cstdio> #include<queue> using namespace std; struct node{ int x,y,s; //x、y表示坐标,s表示时间 }; queue<node>q; int n,m,t,r1,c1,r2,c2,dp[110][110][20]; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; //移动 string s[110]; int main() { cin>>n>>m>>t; for(int i=1;i<=n;i++) cin>>s[i]; cin>>r1>>c1>>r2>>c2; dp[r1][c1][0]=1; //初始方案数为1 q.push(node{r1,c1,0}); while(!q.empty()) { node u=q.front(); q.pop(); for(int i=0;i<4;i++) { node th; th.x=u.x+dx[i]; th.y=u.y+dy[i]; th.s=u.s+1; if(dp[th.x][th.y][th.s]) { dp[th.x][th.y][th.s]+=dp[u.x][u.y][u.s]; continue; //当前状态曾被拓展 } if(th.x<1||th.x>n||th.y<1||th.y>m||s[th.x][th.y-1]=='*'||th.s>t) continue; //越界或不能走或超时,跳过 dp[th.x][th.y][th.s]+=dp[u.x][u.y][u.s]; //计数 q.push(th); } } cout<<dp[r2][c2][t]<<endl; return 0; }