题目描述
题解
看题了之后算了算,步数只有15步,似乎加了这个剪枝之后状态很少啊= =于是直接开始码bfs。码出来了之后发现对拍大数据老是出错,而且把剪枝加的越少数越小!原来我忽略了一个非常重要的问题:队列空间!!!虽然是循环队列,但是由于同时入队的元素非常多,有可能把很多有用的状态覆盖掉!
那么bfs就没法写了,不过dfs是资瓷的,因为递归层数最多是15.不过这道题其实是一道非常简单的dp,设f(i,j,k)表示第i步走到第(j,k)个格子时的方案数,然后就可以递推了。如果丧心病狂一点卡卡内存什么的还可以用滚动优化。
代码
dfs
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 105
int n,m,T,sx,sy,tx,ty,ans;
char squ[N][N],s[N];
int dx[4]={0,0,-1,1};int dy[4]={1,-1,0,0};
int Abs(int x)
{
return (x>0)?x:-x;
}
void dfs(int x,int y,int dep)
{
if (x==tx&&y==ty&&dep==T)
{
ans++;
return;
}
if (dep==T) return;
for (int i=0;i<4;++i)
{
int xx=x+dx[i],yy=y+dy[i];
if (xx<1||xx>n||yy<1||yy>m||squ[xx][yy]=='*') continue;
if (dep+1+Abs(tx-xx)+Abs(ty-yy)>T) continue;
if (dep+1<=T) dfs(xx,yy,dep+1);
}
}
int main()
{
scanf("%d%d%d\n",&n,&m,&T);
for (int i=1;i<=n;++i)
{
gets(s);
for (int j=1;j<=m;++j) squ[i][j]=s[j-1];
}
scanf("%d%d%d%d",&sx,&sy,&tx,&ty);
if (squ[sx][sy]=='*'||squ[tx][ty]=='*')
{
puts("0");
return 0;
}
dfs(sx,sy,0);
printf("%d\n",ans);
}
dp
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 105
int n,m,T,sx,sy,tx,ty;
char squ[N][N],s[N];
int dx[4]={0,0,-1,1};int dy[4]={1,-1,0,0};
int f[20][N][N];
int main()
{
scanf("%d%d%d\n",&n,&m,&T);
for (int i=1;i<=n;++i)
{
gets(s);
for (int j=1;j<=m;++j) squ[i][j]=s[j-1];
}
scanf("%d%d%d%d",&sx,&sy,&tx,&ty);
if (squ[sx][sy]=='*'||squ[tx][ty]=='*')
{
puts("0");
return 0;
}
f[0][sx][sy]=1;
for (int i=1;i<=T;++i)
{
for (int j=1;j<=n;++j)
for (int k=1;k<=m;++k)
{
if (squ[j][k]=='*') continue;
for (int l=0;l<4;++l)
{
int x=j+dx[l],y=k+dy[l];
if (x<1||x>n||y<1||y>m||squ[x][y]=='*') continue;
f[i][j][k]+=f[i-1][x][y];
}
}
}
printf("%d\n",f[T][tx][ty]);
}
总结
①有关于“步数”的bfs原来还可以向dp转化!并且状态之和上一维相关。