• 洛谷P1379 八数码难题


    洛谷P1379 八数码难题

    题意简述

    洛谷

    Solution

    这是一道蓝题,蓝色是水的颜色,所以这是一道水题。

    显然用一个structvector,再用一个queue进行bfs,用一个set记录是否在队列中,用一个map记录搜索到的目标状态需要的步数,我们就可以得到一个时间复杂度非常饱满类似于最短路的思想的bfs啦!

    然而只有(37ptsdots)

    这里考虑将structvector使用状态压缩进一个long long里面,暂时先把queue,setmap保留,你就有(97pts)了!(这难道不是水题吗)

    坚持不开(O_2)的基本原则(虽然用了这么多STL开(O_2)应该会很爽),我们可以手写队列,setmap改成hash表,就可以通过这道题了!

    image-20201201164034496

    看上去很慢是不是……当然还有很多很多的优化,如双向宽搜(Astar),(IDAstardots)

    所以这是一道很好的搜索优化练手题!

    Code

    状态压缩+手写队列+普通(bfs)

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include<set>
    #include<queue>
    #include<vector>
    #define IL inline
    #define re register
    #define LL long long
    #define ULL unsigned long long
    #ifdef TH
    #define debug printf("Now is %d
    ",__LINE__);
    #else
    #define debug
    #endif
    using namespace std;
    
    template<class T>inline void read(T&x)
    {
    	char ch=getchar();
    	int fu;
    	while(!isdigit(ch)&&ch!='-') ch=getchar();
    	if(ch=='-') fu=-1,ch=getchar();
    	x=ch-'0';ch=getchar();
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	x*=fu;
    }
    inline int read()
    {
    	int x=0,fu=1;
    	char ch=getchar();
    	while(!isdigit(ch)&&ch!='-') ch=getchar();
    	if(ch=='-') fu=-1,ch=getchar();
    	x=ch-'0';ch=getchar();
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return x*fu;
    }
    int G[55];
    template<class T>inline void write(T x)
    {
    	int g=0;
    	if(x<0) x=-x,putchar('-');
    	do{G[++g]=x%10;x/=10;}while(x);
    	for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('
    ');
    }
    
    map<LL,int>dis;
    set<LL>online;
    //queue<LL>q;
    LL q[1000000];int l,r;
    const LL goal=123804765;
    int dt[4][2]={1,0,-1,0,0,1,0,-1};
    int now[3][3];
    int i,j,way;
    void bfs()
    {
    //	q.push(read());
    	q[++r]=read();
    	LL x,zx,zy,t,tx,ty;
    	while(/*!q.empty()*/l<=r)
    	{
    //		t=x=q.front();
    //		q.pop();
    		t=x=q[l++];
    		online.erase(x);
    		if(x==goal)
    		{
    			write(dis[x]);
    			return;
    		}
    		for(i=2;i>=0;i--)
    		for(j=2;j>=0;j--)
    		{
    			now[i][j]=t%10;
    			t/=10;
    			if(now[i][j]==0) zx=i,zy=j;
    		}
    //		for(int i=0;i<3;i++)
    //		{
    //			for(int j=0;j<3;j++)
    //			{
    //				cout<<now[i][j]<<" ";
    //			}
    //			cout<<endl;
    //		}
    //		cout<<endl;
    		for(way=0;way<4;way++)
    		{
    			tx=zx+dt[way][0];
    			ty=zy+dt[way][1];
    			if(tx<0||ty<0||tx>2||ty>2) continue;
    			swap(now[tx][ty],now[zx][zy]);
    			t=0;
    			for(i=0;i<3;i++)
    			for(j=0;j<3;j++)
    			{
    				t=t*10;
    				t+=now[i][j];
    			}
    //			cout<<t<<endl;
    			if(dis.find(t)==dis.end())
    			{
    				dis[t]=dis[x]+1;
    //				q.push(t);
    				q[++r]=t;
    				online.insert(t);
    			}
    			else
    			{
    				if(dis[t]>dis[x]+1)
    				{
    					dis[t]=dis[x]+1;
    					if(online.find(t)==online.end())
    					{
    						online.insert(t);
    //						q.push(t);
    						q[++r]=t;
    					}
    				}
    			}
    			swap(now[tx][ty],now[zx][zy]);
    		}
    	}
    }
    
    int main()
    {
    	bfs();
    	
    	return 0;
    }
    
  • 相关阅读:
    Linux系统设置中文
    跟着小白学Linux基础命令系列
    Linux小白基础练习题
    htop命令超级好玩用法
    sed命令用法
    Linux三剑客grep命令的使用技巧
    Linux忘记密码如何修改密码
    决心书
    Linux无法上网,ping不通百度的解决方法
    AE 创建shp图层
  • 原文地址:https://www.cnblogs.com/send-off-a-friend/p/14069178.html
Copyright © 2020-2023  润新知