版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89435719
欢迎大家访问我的老师的OJ———caioj.cn
题目描述
作为经典的八数码问题
我就不描述题面了吧。
思路
普通的八数码就是宽搜嘛,我就不讲了。(我实在太懒了)
于是乎,我开始使用
乱搞。
关于
,详参第
短路
我们这里设估价函数
为当前状态每一个数到目标状态每一个数的曼哈顿距离之和。
因为我们至少要
的步数才能到达目标状态。
所以就好啦。
顺便用康托展开,加速一下。
POJ1077
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<cstdlib>
using namespace std;
const int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
const char A[4]={'l','r','u','d'};
int d[10];
inline void pre(){d[0]=1;for(int i=1;i<=8;i++)d[i]=d[i-1]*i;}
struct node
{
int f,dis,x,y,k,a[4][4];
string ans;
node(){ans="";memset(a,0,sizeof(a));}
bool operator <(const node a)const{return f==a.f?dis>a.dis:f>a.f;}
inline int myabs(int x){return x<0?-x:x;}
inline void kt()
{
k=0;
int b[20],len=0;
for(int i=1;i<=3;i++)for(int j=1;j<=3;j++)b[++len]=a[i][j]+1;//相当于将一个3*3的图排成一行;
bool bo[20];memset(bo,false,sizeof(bo));//初始化
//统计当前这个是第几个康托排列
for(int i=1;i<=9;i++)
{
for(int j=1;j<b[i];j++)
{
if(bo[j]==false)
{
k+=d[9-i];//9-i==0时,不会执行这一句
}
}
bo[b[i]]=true;
}
}
inline void get(const node &ed)
{
f=dis;int x1=1,y1=1;bool ap[10];memset(ap,false,sizeof(ap));
while(x1<3)
{
if(y1==4)x1++,y1=1;
bool bk=false;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(ap[a[i][j]])continue;
if(a[i][j]==ed.a[x1][y1])
{
ap[a[i][j]]=true;
f+=myabs(i-x1)+myabs(j-y1);
y1++;bk=true;break;
}
}
if(bk==true)break;
}
}
}
};
bool vis[500010];
int main()
{
pre();
node st,ed;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
char s[3];scanf("%s",s+1);
if(s[1]=='x')st.x=i,st.y=j;
else st.a[i][j]=s[1]-'0';
}
}
st.kt();
ed.a[1][1]=1;ed.a[1][2]=2;ed.a[1][3]=3;
ed.a[2][1]=4;ed.a[2][2]=5;ed.a[2][3]=6;
ed.a[3][1]=7;ed.a[3][2]=8;ed.x=3,ed.y=3;
ed.kt();
priority_queue<node>q;
q.push(st);
while(!q.empty())
{
node t=q.top();q.pop();
for(int i=0;i<4;i++)
{
node nxt=t;
nxt.x+=dx[i];nxt.y+=dy[i];
int x=nxt.x,y=nxt.y;
if(x<1||x>3||y<1||y>3)continue;
int tw=nxt.a[t.x][t.y];nxt.a[t.x][t.y]=nxt.a[x][y];nxt.a[x][y]=tw;
nxt.kt();
if(vis[nxt.k])continue;
nxt.dis++;nxt.get(ed);nxt.ans+=A[i];vis[nxt.k]=true;
if(nxt.k==ed.k){cout<<nxt.ans<<endl;return 0;}
q.push(nxt);
}
}
puts("unsolvable");
return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int dx[4]={0,1,-1,0};
const int dy[4]={1,0,0,-1};
int d[9];
void pre()
{
d[0]=1;for(int i=1;i<=8;i++)d[i]=d[i-1]*i;
}
struct node
{
int dis,f,k,x,y,ans;
int a[5][5];
node(){dis=k=f=0;memset(a,0,sizeof(a));x=y=0;}
bool operator <(const node &a)const{return f==a.f?dis>a.dis:f>a.f;}//重构小根堆
inline void kt()//康托展开
{
k=0;
int b[20],len=0;
for(int i=1;i<=3;i++)for(int j=1;j<=3;j++)b[++len]=a[i][j]+1;//相当于将一个3*3的图排成一行;
bool bo[20];memset(bo,false,sizeof(bo));//初始化
//统计当前这个是第几个康托排列
for(int i=1;i<=9;i++)
{
for(int j=1;j<b[i];j++)
{
if(bo[j]==false)
{
k+=d[9-i];
}
}
bo[b[i]]=true;
}
}
inline void find_f(const node &ed)//A*的估计函数f
{
int x1=1,y1=1;bool ap[10];memset(ap,false,sizeof(ap));
f=dis;
while(x1<=3)
{
if(y1==4)x1++,y1=1;
bool bk=true;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(ap[ed.a[i][j]])continue;
if(ed.a[i][j]==a[x1][y1])
{
f+=abs(x1-i)+abs(y1-j);ap[a[x1][y1]]=true;
y1++;
bk=false;
break;
}
}
if(bk==false)break;
}
}
}
};
node st,ed;
priority_queue<node>q;
bool v[510000];
int main()
{
pre();
memset(v,false,sizeof(v));
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
char c=getchar();
st.a[i][j]=c-'0';if(st.a[i][j]==0){st.x=i,st.y=j;}
}
}
ed.a[1][1]=1;ed.a[1][2]=2;ed.a[1][3]=3;
ed.a[2][1]=8;ed.a[2][2]=0;ed.a[2][3]=4;
ed.a[3][1]=7;ed.a[3][2]=6;ed.a[3][3]=5;
ed.x=2,ed.y=2;
st.kt();ed.kt();
if(st.k==ed.k){printf("0\n");return 0;}
v[st.k]=true;st.dis=0;st.find_f(ed);
q.push(st);
while(!q.empty())
{
node t=q.top();
q.pop();
for(int i=0;i<4;i++)
{
node now=t;
int x=now.x+dx[i],y=now.y+dy[i];
if(x<1||x>3||y<1||y>3)continue;
int tw=now.a[now.x][now.y];now.a[now.x][now.y]=now.a[x][y];now.a[x][y]=tw;
now.x=x,now.y=y;
now.dis++;
now.kt();
if(v[now.k])continue;
now.find_f(ed);
v[now.k]=true;
if(now.k==ed.k){printf("%d\n",now.dis);return 0;}
q.push(now);
}
}
return 0;
}
caioj1046(数据贼水)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int dx[4]={0,-1,0,1};
const int dy[4]={-1,0,1,0};
int d[9];
void pre()
{
d[0]=1;for(int i=1;i<=8;i++)d[i]=d[i-1]*i;
}
struct node
{
int dis,f,k,x,y;
int a[5][5];
node(){dis=k=f=0;memset(a,0,sizeof(a));x=y=0;}
bool operator <(const node &a)const{return f==a.f?dis>a.dis:f>a.f;}
inline void kt()
{
k=0;
int b[20],len=0;
for(int i=1;i<=3;i++)for(int j=1;j<=3;j++)b[++len]=a[i][j]+1;//相当于将一个3*3的图排成一行;
bool bo[20];memset(bo,false,sizeof(bo));//初始化
//统计当前这个是第几个康托排列
for(int i=1;i<=9;i++)
{
for(int j=1;j<b[i];j++)
{
if(bo[j]==false)
{
k+=d[9-i];
}
}
bo[b[i]]=true;
}
}
inline void find_f(const node &ed)
{
int x1=1,y1=1;bool ap[10];memset(ap,false,sizeof(ap));
f=dis;
while(x1<=3)
{
if(y1==4)x1++,y1=1;
bool bk=true;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(ap[ed.a[i][j]])continue;
if(ed.a[i][j]==a[x1][y1])
{
f+=abs(x1-i)+abs(y1-j);ap[a[x1][y1]]=true;
y1++;
bk=false;
break;
}
}
if(bk==false)break;
}
}
}
};
node st,ed;
priority_queue<node>q;
bool v[1100000];
int main()
{
pre();
memset(v,false,sizeof(v));
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
scanf("%d",&st.a[i][j]);
if(st.a[i][j]==0){st.x=i,st.y=j;}
}
}
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
scanf("%d",&ed.a[i][j]);
if(ed.a[i][j]==0){ed.x=i,ed.y=j;}
}
}
st.kt();ed.kt();v[st.k]=true;
st.dis=1;
st.find_f(ed);
q.push(st);
while(!q.empty())
{
node t=q.top();
q.pop();
for(int i=0;i<4;i++)
{
node now=t;
int x=now.x+dx[i],y=now.y+dy[i];
if(x<1||x>3||y<1||y>3)continue;
int tw=now.a[now.x][now.y];now.a[now.x][now.y]=now.a[x][y];now.a[x][y]=tw;
now.x=x,now.y=y;
now.dis++;
now.kt();
if(v[now.k])continue;
now.find_f(ed);
v[now.k]=true;
q.push(now);
if(now.k==ed.k){printf("%d\n",now.dis);return 0;}
}
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<cstdlib>
using namespace std;
const int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
const char A[4]={'l','r','u','d'};
int d[10];
int dep;
inline void pre(){d[0]=1;for(int i=1;i<=8;i++)d[i]=d[i-1]*i;}
struct node
{
int f,dis,x,y,k,a[4][4];
string ans;
node(){ans="";memset(a,0,sizeof(a));}
inline int myabs(int x){return x<0?-x:x;}
inline void kt()
{
k=0;
int b[20],len=0;
for(int i=1;i<=3;i++)for(int j=1;j<=3;j++)b[++len]=a[i][j]+1;//相当于将一个3*3的图排成一行;
bool bo[20];memset(bo,false,sizeof(bo));//初始化
//统计当前这个是第几个康托排列
for(int i=1;i<=9;i++)
{
for(int j=1;j<b[i];j++)
{
if(bo[j]==false)
{
k+=d[9-i];//9-i==0时,不会执行这一句
}
}
bo[b[i]]=true;
}
}
inline void get(const node &ed)
{
f=dis;int x1=1,y1=1;bool ap[10];memset(ap,false,sizeof(ap));
while(x1<3)
{
if(y1==4)x1++,y1=1;
bool bk=false;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(ap[a[i][j]])continue;
if(a[i][j]==ed.a[x1][y1])
{
ap[a[i][j]]=true;
f+=myabs(i-x1)+myabs(j-y1);
y1++;bk=true;break;
}
}
if(bk==true)break;
}
}
}
};
node st,ed;
bool vis[500010];
bool dfs(node t)
{
if(t.k==ed.k)
{
cout<<t.ans<<endl;
return 1;
}
if(t.f>dep)return 0;
for(int i=0;i<4;i++)
{
node nxt=t;
nxt.x+=dx[i];nxt.y+=dy[i];
int x=nxt.x,y=nxt.y;
if(x<1||x>3||y<1||y>3)continue;
int tw=nxt.a[t.x][t.y];nxt.a[t.x][t.y]=nxt.a[x][y];nxt.a[x][y]=tw;
nxt.kt();if(vis[nxt.k])continue;
nxt.dis++;nxt.get(ed);nxt.ans+=A[i];vis[nxt.k]=true;
if(dfs(nxt))return 1;
vis[nxt.k]=false;
}
return 0;
}
int main()
{
pre();
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
char s[3];scanf("%s",s+1);
if(s[1]=='x')st.x=i,st.y=j;
else st.a[i][j]=s[1]-'0';
}
}
st.kt();
ed.a[1][1]=1;ed.a[1][2]=2;ed.a[1][3]=3;
ed.a[2][1]=4;ed.a[2][2]=5;ed.a[2][3]=6;
ed.a[3][1]=7;ed.a[3][2]=8;ed.x=3,ed.y=3;
ed.kt();
dep=0;
while(1&&dep<=30)
{
if(dfs(st))return 0;
dep++;
}
puts("unsolvable");
return 0;
}