zoukankan      html  css  js  c++  java
  • SJTU T4143 推箱子

    问题描述

    推箱子是一款经典的小游戏。游戏要求玩家将若干个箱子推到指定的位置,并以箱子移动次数最少作为目标。 现在,我们只需要考虑一个简化的版本——只有一个箱子。对于一张给定的地图,你需要判断是否可以将箱子推到目标位置,如果可以,你还需要求出箱子最少的移动次数。

    输入格式

    第一行有两个用单个空格分隔的正整数n,m(n,m<=100),表示输入一张n∗m的地图。 接下来n行,每行m个字母,字母分别是S, M, P, K, w,意义如下: S – 表示地图中的墙 M – 表示玩家的初始位置 P – 表示箱子的初始位置 K- 表示箱子的目标位置 w – 表示地图中的空格 M, P 和 K 在文件中只出现一次

    输出格式

    如果箱子不能移动到目的位置,则输出NO。

    如果箱子能移动到目的位置,则输出最小的移动次数。

    样例输入

    10 12
    SSSSSSSSSSSS
    SwwwwwwwSSSS
    SwSSSSwwSSSS
    SwSSSSwwSKSS
    SwSSSSwwSwSS
    SwwwwwPwwwww
    SSSSSSSwSwSw
    SSSSSSMwSwww
    SSSSSSSSSSSS
    SSSSSSSSSSSS
    

    样例输出

    7
    
    

    数据范围

    对于10%的数据: n=1或m=1

    另10%的数据: n=5,m=100或n=100,m=5

    对于30%的数据: n,m<=50

    对于100%的数据: n,m<=100



    题目大意大概就是这样

    这个题也算是祖传题了

    上一届的yveh学长当时这题就没能做出来

    点名批评某助教

    大概讲一下思路以及心路历程

    完整的代码为了(防止学弟学妹们借鉴,就不放了)

    毕竟是祖传题嘛!!

    大概主要是对箱子进行bfs,然后每一个点的状态存储当前的x,当前的y,当前的s(已走路程),还有上一次移动推过来的方向dir。

    struct Node{
    	int x,y,s,dir;
    };
    

    然后每次对箱子bfs之前,都要对人进行bfs,看看能不能到箱子的四个位置,这时候上一次的dir就起作用了,可以知道人的初始位置

    于是我就这样做了

    不幸地TLE了

    之后询问了以下周围同学,然后优化了一些步骤的先后顺序

    So——速度大概快了负的百分之一吧!

    我太难了

    之后我就尝试了一些黑科技

    强行加上头文件的O2O3Ofast优化之类的

    可参考我的另一篇文章

    卡常的编译命令(含O2优化)

    当然还是没用啦

    之后班里面的Hz同学告诉我关于vis数组的判断可以优化的方法

    like this:

    多次要用到vis[]时
    可以用把vis改成int型,然后每次使用cnt++,如果cnt==vis[],说明此次已经遍历到了;
    反之,就让vis[]=cnt;
    
    

    速度好像是快了那么一点点点点

    然而还是没啥用

    然后,然后……

    又get到一个技巧,就是每次对人进行bfs的时候,不要bfs四个方向,而是一次bfs;

    因为起点都是一样的嘛,就是终点不太一样

    然后一次bfs全图,再判断这个点能不能到

    理论上这个可以让程序快四倍

    我又交了
    ——————又T了

    95分真的是气死人

    不过我们班好多同学都卡在了95分上面;

    最后的最后

    我因为以前一直用的是STL里面的queue,毕竟我觉得更加方便,可以用结构体

    现在——————不得不改成用数组表示队列了

    确实我知道这样要快一点,但是基本上这要把整个程序都改一遍


    又能咋办呢?

    最后 费了好长一段时间,总算改完了

    (如果不算之前的尝试吧)1Y !!!

    小作业之后————感叹————STL害人!!!

    真的不知道我什么时候又会真香

    真香!

    下面贴一点代码

    关于最后表示队列的数组

    int Q1[410000],Q2[410000],Q3[410000],Q4[410000],L,R;
    int qx[410000],qy[410000],l,r;
    

    箱子的bfs

    void bfs(){
        L=0,R=0; 
    	for(int i=0;i<4;++i){
    		int nowx = th.x;
    		int nowy = th.y;
    	    int nows=0;
    	    int nowdir=i;
    		if(getbfs(my.x,my.y,nowx-dx[i],nowy-dy[i],th.x,th.y)){
    			R++;
    			Q1[R]=nowx,Q2[R]=nowy,Q3[R]=nows,Q4[R]=nowdir;
    			vis[nowdir][nowx][nowy]=true;
    		}
    	}
    	while(L<R){
    		L++;
    		int nowx=Q1[L];
    		int nowy=Q2[L];
    		int nows=Q3[L];
    		int nowdir=Q4[L];
    		BFS(nowx-dx[nowdir],nowy-dy[nowdir],nowx,nowy);
    		for(int i=0;i<4;++i){
    			int newsx=nowx+dx[i];
        		int newsy=nowy+dy[i];
        		int newss=nows+1;
        		int newsdir=i;
        		if(v[nowx-dx[i]][nowy-dy[i]]!=cnt) continue;
    			if(Map[newsx][newsy]=='S'||newsx<1||newsx>n||newsy<1||newsy>m||vis[i][newsx][newsy]==true) continue;
    			if(Map[newsx][newsy]=='K'){
    				flag=newss;
    				return;
    			}
    			R++;
    			Q1[R]=newsx,Q2[R]=newsy,Q3[R]=newss,Q4[R]=newsdir;
    			vis[i][newsx][newsy]=true;
    		}
    	}
    	return;
    }
    
    
    

    人的bfs

    void BFS(const int &x,const int &y,const int &tx,const int &ty){
    	cnt++;
    	l=0,r=1;
    	qx[r]=x,qy[r]=y;
        v[x][y]=cnt;
        while(l<r){
        	l++;
        	int nowx=qx[l],nowy=qy[l];
        	for(int i=0;i<4;++i){
        		int newsx=nowx+dx[i];
        		int newsy=nowy+dy[i];
        		if(Map[newsx][newsy]=='S'||(newsx==tx&&newsy==ty)||newsx<1||newsx>n||newsy<1||newsy>m) continue;
        		if(v[newsx][newsy]==cnt) continue;
        		else{
        			v[newsx][newsy]=cnt;
        			r++;
        			qx[r]=newsx,qy[r]=newsy;
        	    }
    		}
    	}
    }
    

    That's all.

  • 相关阅读:
    java--volatile关键字
    java--线程异常处理器
    java--线程池
    Supervisor安装和使用
    网络协议--HTTP
    1.Nginx简介
    Nginx配置实战
    Redis面试题
    SpringBoot--集成swagger2
    缓存的优缺点
  • 原文地址:https://www.cnblogs.com/battlin/p/11858661.html
Copyright © 2011-2022 走看看