洛谷P1379 八数码难题
题意简述
见洛谷。
Solution
这是一道蓝题,蓝色是水的颜色,所以这是一道水题。
显然用一个struct
套vector
,再用一个queue
进行bfs
,用一个set记录是否在队列中,用一个map记录搜索到的目标状态需要的步数,我们就可以得到一个时间复杂度非常饱满类似于最短路的思想的bfs
啦!
然而只有(37ptsdots)
这里考虑将struct
和vector
使用状态压缩进一个long long
里面,暂时先把queue
,set
和map
保留,你就有(97pts)了!(这难道不是水题吗)
坚持不开(O_2)的基本原则(虽然用了这么多STL开(O_2)应该会很爽),我们可以手写队列,set
,map
改成hash
表,就可以通过这道题了!
看上去很慢是不是……当然还有很多很多的优化,如双向宽搜,(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;
}