记忆化DFS/BFS: NEEPUOJ3009噩梦


乍一看是迷宫最短路问题,用BFS,DFS都可以解决。这道题的特点是有重置,在走迷宫求最短路径这个根本目的不变的同时,要求如果没有重置炸弹或者到达出口不能连续移动超过5次。

地图大小并不大(<=8),时间要求1000ms。首先考虑DFS搜索是否可行,第一次提交的是标准DFS搜索,遇到炸弹重置点重置剩余可走步数,超出范围或者超出可走步数返回搜索。然而超时了,有许多冗余调用没有提前退出,因此使用矩阵记忆每次搜索过的该点历史最短步数和最多剩余时间。当再一次搜索至该点时,如果此次搜索的步数和时间均比历史记录差,则放弃继续搜索。

这次调整后成功通过,OJ计时仅1ms,说明去冗效果还是很不错的。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<limits.h>
#define MAX 9
int map[MAX][MAX],step[MAX][MAX],time[MAX][MAX];
int n,m,minx;
void dfs(int x,int y,int len,int cnt)
{
    //printf("DFS***x=%d,y=%d,len=%d,cnt=%d,step=%d,time=%d\n",x,y,len,cnt,step[x][y],time[x][y]);
    if(x<0 || y<0 || x>=n || y>=m)
		return;
    if(len<=0 || cnt>=minx)
		return;
    if(map[x][y]==0)
		return;
    if(map[x][y]==3)
    {
        if(cnt<minx)
	    minx=cnt;
        return;
    }
    if(map[x][y]==4)
        len=6;
    if(cnt>=step[x][y] && time[x][y]>=len)
	return;
    step[x][y]=cnt;
    time[x][y]=len;
    int tx,ty,i;
    int dir[4][2]={1,0,-1,0,0,1,0,-1};
    for(i=0;i<4;i++)
    {
        tx=x+dir[i][0];
        ty=y+dir[i][1];
        dfs(tx,ty,len-1,cnt+1);
    }
}
int main(int argc,char* argv[])
{
    int num,i,j,len,cnt;
    scanf("%d",&num);
    while(num--)
	{
        scanf("%d %d",&n,&m);
        int sx,sy;
        for(i=0;i<n;++i)
		{
            for(j=0;j<m;++j)
	    {
                time[i][j]=0;
                step[i][j]=INT_MAX-3;
                scanf("%d",&map[i][j]);
                if(map[i][j]==2)
		{
                    sx = i;
                    sy = j;
                }
            }
        }
        len = 6;
        cnt = 0;
        minx = INT_MAX;
        dfs(sx,sy,len,cnt);
        if(minx==INT_MAX)
            printf("-1\n");
    	else
            printf("%d\n",minx);
    }
    return EXIT_SUCCESS;
}

用记忆化DFS解决,思路明确写起来还是比较容易的。但是用BFS实现肯定是更快,队列由地图XY坐标、已用时间和炸弹剩余时间组成。搜索的同时,当当前位置的炸弹剩余时间等于1的时候,跳过对当前位置的继续搜索。每走出一步都需要判断此次炸弹剩余时间是否多于历史时间,如果多于说明继续搜索是有意义的,并刷新炸弹剩余时间记录。如果一直没有搜索到终点则返回-1结束BFS搜索。OJ测试时间少于1ms。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node
{
    int x,y;
    int time;
    int bomb;
};
int map[9][9];
int book[9][9];
int BFS(int s1,int s2,int m,int n)
{
	struct node que[81];
	int move[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
	int head=1;
	int body=1;
	que[body].x=s1;
	que[body].y=s2;
	que[body].time=0;
	que[body].bomb=6;
	body++;
    book[s1][s2]=6;
    while(head<body)
    {
        if(que[head].bomb-1==0)
        {
        	head++;
        	continue;
        }
		int i;
        for(i=0;i<4;i++)
        {
            int cx=que[head].x+move[i][0];
            int cy=que[head].y+move[i][1];
            if(cx<1||cx>m||cy<1||cy>n)
				continue;
			if(!map[cx][cy])
				continue;
            if(book[cx][cy]<que[head].bomb)  
            {
                if(map[cx][cy]==1||map[cx][cy]==3)
                {

                        que[body].bomb=que[head].bomb-1;
                        que[body].x=cx;
                        que[body].y=cy;
                        que[body].time=que[head].time+1;
                        book[cx][cy]=que[body].bomb;
						body++;
                }
                else if(map[cx][cy]==4)
                {

                        que[body].bomb=6;
                        que[body].x=cx;
                        que[body].y=cy;
                        que[body].time=que[head].time+1;
                        book[cx][cy]=6;
						body++;
                }
		        if(map[que[body-1].x][que[body-1].y]==3)
		        {
		            return que[body-1].time;
		        }
	        }
	    }
        head++;
    }
    return -1;
}
int main(int argc,char* argv[])
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
    	int i,j,s1,s2;
    	int m,n;
        scanf("%d%d",&m,&n);
        for(i=1;i<=m;i++)
        {
            for(j=1;j<=n;j++)
            {
                scanf("%d",&map[i][j]);
                if(map[i][j]==2)
                {
                    s1=i;
                    s2=j;
                }
            }
        }
        memset(book,0,sizeof(book));
       	printf("%d\n", BFS(s1,s2,m,n));
    }
    return 0;
}

THE END

猜你喜欢

转载自blog.csdn.net/belous_zxy/article/details/80017030