https://hihocoder.com/problemset/problem/1312
题意:是中文
思路:启发式搜索
意求从一个状态到另一个状态
hash每个状态存在一个数组里,排序,用二分找当前状态的下标。
bfs每种状态,如果和最终状态相同则更新答案。话不多说看代码吧
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<set>
using namespace std;
int t[10]={1,2,3,4,5,6,7,8},ed=87654321,vis[10],ten[20],flag[400000+10],ans;
struct node
{
int num,pos,h,g;
node(){};
node(int num,int pos,int h,int g){this->num=num;this->pos=pos;this->h=h;this->g=g;}
bool operator < (const node & a)const
{
if((g+h)==(a.g+a.h))return num<a.num;
return (g+h)<(a.g+a.h);
}
}hs[400000+10];
set<node>st;
set<node>::iterator it;
int tot=0;
void hashdfs(int step,int difnum,int _0pos,int nownum)
{
if(step==9)
{
hs[tot]=node(nownum,_0pos,0,difnum);
tot++;
return;
}
for(int i=0;i<9;i++)
{
if(vis[i]==0)
{
vis[i]=1;
int tmpdif=difnum,tmppos=_0pos;
if(i!=t[step])tmpdif++;
if(i==0)tmppos=step;
hashdfs(step+1,tmpdif,tmppos,nownum+ten[step]*i);
vis[i]=0;
}
}
}
bool cmp(node a, node b){return a.num<b.num;}
int erfen(int num)
{
int l=0,r=tot-1,ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(hs[mid].num<=num)
{
l=mid+1;
ans=mid;
}
else r=mid-1;
}
return ans;
}
void sw(node nw,int pos,int n1pos)
{
int tmpnum=nw.num,tmpg=nw.g;
int n1;
n1=nw.num/ten[n1pos]%10;
if(n1==t[n1pos])tmpg++;
if(0==t[pos])tmpg++;
if(n1==t[pos])tmpg--;
if(0==t[n1pos])tmpg--;
tmpnum-=n1*ten[n1pos];
tmpnum+=n1*ten[pos];
st.insert(node(tmpnum,n1pos,nw.h+1,tmpg));
}
void bfs()
{
while(!st.empty())
{
node now=*st.begin();
st.erase(st.begin());
int p=erfen(now.num);
if(flag[p])continue;
flag[p]=1;
if(now.num==ed){ans=min(ans,now.h);break;}
if(now.h>ans)continue;
//四个方向
if(hs[p].pos-3>=0)
sw(now,hs[p].pos,hs[p].pos-3);
if(hs[p].pos+3<9)
sw(now,hs[p].pos,hs[p].pos+3);
if((hs[p].pos-1)/3==hs[p].pos/3&&hs[p].pos>0)
sw(now,hs[p].pos,hs[p].pos-1);
if((hs[p].pos+1)/3==hs[p].pos/3)
sw(now,hs[p].pos,hs[p].pos+1);
}
}
int main()
{
ten[0]=1;
for(int i=1;i<9;i++)ten[i]=ten[i-1]*10;
memset(vis,0,sizeof vis);
hashdfs(0,0,-1,0);
sort(hs,hs+tot,cmp);//hash
int tcas;
scanf("%d",&tcas);
while(tcas--)
{
st.clear();
memset(flag,0,sizeof flag);
ans=99999999;
int init=0,x,p,gnum=0;
for(int i=0;i<9;i++)
{
scanf("%d",&x);
if(x==0)p=i;
if(x!=t[i])gnum++;
init+=x*ten[i];
}
st.insert(node(init,p,0,gnum));
bfs();//
if(ans==99999999)printf("No Solution!\n");
else printf("%d\n",ans);
}
return 0;
}