my
八数码问题
首先判断是否有解。这里有一个条件:将八数码转化为序列后如果逆序对数为偶数,一定有解,否则一定无解。
充分性难证明,只证明必要性:只要是有解必定是偶数。
行内移动序列没有变,数量不变。
如果上下移动发现逆序对变化是
而答案序列逆序对为
显然估价函数应该设置为所有数与它目标位置之间的曼哈顿距离之和,因为每次最多只能将一个数向目标位置靠近,而且一般不能达到最好的情况。
#include<bits/stdc++.h>
using namespace std;
#define f first
#define s second
typedef pair<int,string> PIS;
int f(string state){
int res=0;
for(int i=0;i<state.size();++i){
int t=state[i]-49;
res+=abs(i/3-t/3)+abs(i%3-t%3);
}
return res;
}
string bfs(string start){
const int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
string op="udlr";
string end="12345678x";
unordered_map<string,int>dist;
unordered_map<string,pair<string,char>>prev;
priority_queue<PIS,vector<PIS>,greater<PIS>>heap;
heap.push({f(start),start});
dist[start]=0;
while(!heap.empty()){
auto t=heap.top();
heap.pop();
string state=t.s;
if(state==end)break;
int step=dist[state];
int x,y;
for(int i=0;i<state.size();++i)
if(state[i]=='x'){
x=i/3,y=i%3;
break;
}
string source=state;
for(int i=0;i<4;++i){
state=source;
int a=x+dx[i],b=y+dy[i];
if(a>=0&&a<3&&b>=0&&b<3){
swap(state[x*3+y],state[a*3+b]);
if(!dist.count(state)||dist[state]>step+1){
dist[state]=step+1;
prev[state]={source,op[i]};
heap.push({dist[state]+f(state),state});
}
}
}
}
string res;
while(end!=start){
res+=prev[end].s;
end=prev[end].f;
}
reverse(res.begin(),res.end());
return res;
}
int main(){
string g,seq;
char c;
while(cin>>c){
g+=c;
if(c!='x')seq+=c;
}
int t=0;
for(int i=0;i<8;++i)
for(int j=i+1;j<8;++j)
if(seq[i]>seq[j])++t;
if(t&1)puts("unsolvable");
else puts(bfs(g).c_str());
return 0;
}
本文作者:wscqwq
本文链接:https://www.cnblogs.com/wscqwq/p/17393799.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步