题意:有个机器人,可以上下左右移动,表格中1表示障碍物,机器人可以连续通过不超过K个障碍物,问从(1,1)出发,到达点(n,m)的最小步数,如果无法到达,输出-1;
很容易想到这是个dfs,但是我的dfsT了
T的代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
using namespace std;
#include<iostream>
const int inf=0x3f3f3f3f;
int a[150][150],book[100][100];
int n,m,k,minn;
void haha(int x,int y,int step,int sum) //sum表示当前还可以连续过多少障碍物
{
int next[4][2]=
{
{-1,0},//上
{0,-1},//左
{0,1}, //右
{1,0}, //下
};
int tx,ty;
if(x==n&&y==m)
{
minn=min(minn,step);
return;
}
for(int i=0; i<4; i++)
{
tx=x+next[i][0];
ty=y+next[i][1];
if(tx<=0||tx>n||ty<=0||ty>m||book[tx][ty]==1) //判断超界
continue;
if(a[tx][ty]==0||(a[tx][ty]==1&&sum>0))
{
book[tx][ty]=1;
haha(tx,ty,step+1,a[tx][ty]==0?k:sum-1); //这里的sum变化应该没错
book[tx][ty]=0;
}
}
return ;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(book,0,sizeof(book));
minn=inf;
scanf("%d %d %d",&n,&m,&k);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
scanf("%d",&a[i][j]);
book[1][1]=1;
haha(1,1,0,k);
if(minn==inf)
printf("-1\n");
else
printf("%d\n",minn);
}
}
但是可以发现,我的dfs的点几乎是没变化的,也就是他一直遍历那么多的点,时间复杂度是O((n*m)^2),这题还是t组输入,t的范围是20,所以总的时间复杂度约为160000*20=3200000.
关于优化:记忆化搜索点
怎么记忆化?开个三维数组,前两维存坐标,后一维存连续通过的障碍物的点,存值为当前状态的最小步数。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
using namespace std;
#include<iostream>
const int inf=0x3f3f3f3f;
int a[150][150],dp[100][100][100];
int n,m,k,minn;
void haha(int x,int y,int step,int sum)
{
int next[4][2]=
{
{-1,0},//上
{0,-1},//左
{0,1}, //右
{1,0}, //下
};
int tx,ty;
if(x==n&&y==m)
{
minn=min(minn,step);
return;
}
for(int i=0; i<4; i++)
{
tx=x+next[i][0];
ty=y+next[i][1];
int ans=sum; //连续通过障碍物的个数
if(tx<=0||tx>n||ty<=0||ty>m) //判断超界
continue;
if(a[tx][ty])
ans++;
else
ans=0;
if((dp[tx][ty][ans]<0||dp[tx][ty][ans]>step+1)&&ans<=k) //这一步减少了dfs的时间复杂度
{
dp[tx][ty][ans]=step+1;
haha(tx,ty,step+1,ans);
}
}
return ;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,-1,sizeof(dp));
minn=inf;
scanf("%d %d %d",&n,&m,&k);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
scanf("%d",&a[i][j]);
haha(1,1,0,0);
if(minn==inf)
printf("-1\n");
else
printf("%d\n",minn);
}
}