1. 程式人生 > 實用技巧 >洛谷P1379 八數碼難題

洛谷P1379 八數碼難題

洛谷P1379 八數碼難題

題意簡述

洛谷

Solution

這是一道藍題,藍色是水的顏色,所以這是一道水題。

顯然用一個structvector,再用一個queue進行bfs,用一個set記錄是否在佇列中,用一個map記錄搜尋到的目標狀態需要的步數,我們就可以得到一個時間複雜度非常飽滿類似於最短路的思想的bfs啦!

然而只有\(37pts\dots\)

這裡考慮將structvector使用狀態壓縮排一個long long裡面,暫時先把queue,setmap保留,你就有\(97pts\)了!(這難道不是水題嗎)

堅持不開\(O_2\)的基本原則(雖然用了這麼多STL開\(O_2\)

應該會很爽),我們可以手寫佇列,setmap改成hash表,就可以通過這道題了!

看上去很慢是不是……當然還有很多很多的優化,如雙向寬搜\(A\star\),\(IDA\star\dots\)

所以這是一道很好的搜尋優化練手題!

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\n",__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('\n');
}

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;
}