您的位置:首页 > 其它

康托展开求八数码问题

2015-01-09 16:49 381 查看
/*
问题描述:
目标状态为:
1 2 3
4 5 6
7 8 0

输入初始状态,求初始状态到最终状态的路径分别
用u(向上),d(向下),l(向左),r(向右)来表示四个方向的移动;
如果有解,则输出路径,否则输出"unsolvable"
有多个输入
*/

#include<iostream>
#include<queue>
#include<string>
#include<cstring>
using namespace std;
long long fac[10] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
const int direction[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };  //0移动的方向
bool closeList[362880 + 10]; //记录一个节点是否被访问过			     // l , r, u, d
char action[5] = "udlr"; //移动的步骤,对应上面的direction
int target = 0; //保存目标状态的康托展开值
int tmptarget[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 }; //目标状态
const int num = 3;

struct Node{
int state[num * num];
int zero; //0的位置
string steps; //从初始节点到当前节点的路径
int cnt; //当前状态的康托展开值
};

//康托展开
int Cantor(int state[9]){
int id = 0;
for (size_t i = 0; i < num * num; i++){
int count = 0;
for (size_t j = i + 1; j < num * num; j++){
if (state[i] > state[j])
count++;
}
id += (count * fac[num * num - i - 1]);
}
return id + 1;
}

int main(int argc, char *argv[]){
target = Cantor(tmptarget);
char ch;
//1 2 3 4 5 x 7 8 6
//2 3 4 1 5 x 7 6 8
while (cin >> ch){ //记得把cin >> ch放在这里,否则会time limit
Node head;
Node next;
if (ch == 'x'){
head.zero = 0;
head.state[0] = 0;
}
else
head.state[0] = ch - '0';
for (int i = 1; i < num * num; i++){
cin >> ch; //输入起始状态
if (ch == 'x'){ //把x换成0
head.zero = i;
head.state[i] = 0;
}
else
head.state[i] = ch - '0';
}
head.cnt = Cantor(head.state);
head.steps = "";

queue<Node> openList;
bool flag = false; //记录是否达到目标状态
string path = ""; //记录从起始节点到目标节点的路径
memset(closeList, false, sizeof(closeList));
openList.push(head);

while (!openList.empty() && !flag){
head = openList.front();
if (head.cnt == target){ //判断是否达到目标状态
flag = true;
path = head.steps;
break;
}
int oldr = head.zero / num; //0所在的行
int oldc = head.zero % num; //0所在的列
for (int i = 0; i < 4; i++){
int newr = oldr + direction[i][0];
int newc = oldc + direction[i][1];
if (newr >= 0 && newr < num && newc >= 0 && newc < num){
next = head;
next.zero = newr * 3 + newc; //0的新位置
next.state[head.zero] = head.state[next.zero];
next.state[next.zero] = 0;
next.cnt = Cantor(next.state);
if (!closeList[next.cnt]){
next.steps = head.steps + action[i];
if (next.cnt == target){
flag = true;
path = next.steps;
break;
}
closeList[next.cnt] = true;
openList.push(next);
}
}
}
openList.pop();
}
if (flag){ //找到解,输出路径
cout << path << "\n";
}
else{
cout << "unsolvable" << "\n";
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: