【SOUTH CENTRAL USA 1998】 eight

【题目链接】

点击打开链接

【算法】

这是经典的八数码问题,据说此题不做人生不完整

这里笔者用的是双向广搜,由于细节较多,笔者花了3h才通过此题

【代码】

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>

using namespace std;

struct info {
		int x,y,h;	
		int a[10];		
};

const int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
const int fac[10] = {1,1,2,6,24,120,720,5040,40320,362880};

int i,d,h1,t1,h2,t2;
int val[10],pre1[500010],pre2[500010],
		step1[500010],step2[500010],visit[500010];
int s[10] = {0,1,2,3,4,5,6,7,8,9};
vector<int> path1,path2;
info q1[500010],q2[500010];
char x;

int getcantorHash(int a[10]) {
		int i,j,s,ret=0;
		for (i = 1; i < 9; i++) {
				s = 0;
				for (j = i + 1; j <= 9; j++) {
						if (a[i] > a[j])
								s++;
				}
				ret += s * fac[9-i];
		}
		return ret;
}

void getpath1(int Hash) {
		int i;
		i = t1;
		while (i > 1) {
				path1.push_back(step1[q1[i].h]);
				i = pre1[q1[i].h];			
		}
		reverse(path1.begin(),path1.end());
		path2.push_back(step2[Hash]);
		i = pre2[Hash];
		while (i > 1) {
				path2.push_back(step2[q2[i].h]);
				i = pre2[q2[i].h];
		}
}

void getpath2(int Hash) {
		path1.push_back(step1[Hash]);
		i =	pre1[Hash];
		while (i > 1) {
				path1.push_back(step1[q1[i].h]);
				i = pre1[q1[i].h];
		}
		reverse(path1.begin(),path1.end());
		i = t2;
		while (i > 1) {
				path2.push_back(step2[q2[i].h]);
				i = pre2[q2[i].h];
		}
}

bool DBFS() {
		int x,y,tx,ty,Hash;
		int arr[10];
		h1 = t1 = h2 = t2 = 1;
		q1[1].x = (d - 1) / 3 + 1;
		q1[1].y = (d - 1) % 3 + 1;
		q1[1].h = getcantorHash(val);
		memcpy((char*)&q1[1].a[1],(char*)&val[1],sizeof(int)*9);
		step1[getcantorHash(val)] = pre1[getcantorHash(val)] = -1;
		visit[getcantorHash(val)] = 1;
		q2[1].x = q2[1].y = 3;
		q2[1].h = getcantorHash(s);
		memcpy((char*)&q2[1].a[1],(char*)&s[1],sizeof(int)*9);
		step2[getcantorHash(s)] = pre2[getcantorHash(s)] = -1;
 		visit[getcantorHash(s)] = 2;
		while ((h1 <= t1) || (h2 <= t2)) {
				x = q1[h1].x; y = q1[h1].y;
				for (i = 0; i < 4; i++) {
						memcpy((char*)&arr[1],(char*)&q1[h1].a[1],sizeof(int)*9);
						tx = x + dir[i][0];
						ty = y + dir[i][1];
						if ((tx <= 0) || (tx > 3) || (ty <= 0) || (ty > 3))
								continue;
						swap(arr[(x-1)*3+y],arr[(tx-1)*3+ty]);
						Hash = getcantorHash(arr);
						if (visit[Hash] == 0) {
								visit[Hash] = 1;
								++t1;
								q1[t1].x = tx;
								q1[t1].y = ty;
								memcpy((char*)&q1[t1].a[1],(char*)&arr[1],sizeof(int)*9);
								q1[t1].h = Hash;
								step1[Hash] = i;
								pre1[Hash] = h1;
						}else if (visit[Hash] == 1) {
								continue;
						}else {
								++t1;
								q1[t1].h = Hash;
								step1[Hash] = i;
								pre1[Hash] = h1;
								getpath1(Hash);
								return true;
						}
				}
				x = q2[h2].x; y = q2[h2].y;
				for (i = 0; i < 4; i++) {
						memcpy((char*)&arr[1],(char*)&q2[h2].a[1],sizeof(int)*9);
						tx = x + dir[i][0];
						ty = y + dir[i][1];
						if ((tx <= 0) || (tx > 3) || (ty <= 0) || (ty > 3))
								continue;
						swap(arr[(x-1)*3+y],arr[(tx-1)*3+ty]);
						Hash = getcantorHash(arr);
						if (visit[Hash] == 0) {
								visit[Hash] = 2;
								++t2;
								q2[t2].x = tx;
								q2[t2].y = ty;
								q2[t2].h = Hash;
								memcpy((char*)&q2[t2].a[1],(char*)&arr[1],sizeof(int)*9);
								step2[Hash] = i;
								pre2[Hash] = h2;
						}else if (visit[Hash] == 2) {
								continue;
						}else {
								++t2;
								q2[t2].h = Hash;
								step2[Hash] = i;
								pre2[Hash] = h2;
								getpath2(Hash);
								return true;
						}
				}
				h1++; h2++;
		}
		return false;
}

void print() {
		int i;
		for (i = 0; i < path1.size(); i++) {
				switch(path1[i]) {
						case 0 : putchar('r');
										 break;
						case 1 : putchar('l');
										 break;
						case 2 : putchar('d');
										 break;
						default : putchar('u');
				}
		}	
		for (i = 0; i < path2.size(); i++) {
				switch(path2[i]) {
						case 0 : putchar('l');
										 break;
						case 1 : putchar('r');
										 break;
						case 2 : putchar('u');
										 break;
						default : putchar('d');
				}
		}
		puts("");
}

int main() {
		
		for (i = 1; i <= 9; i++) {
				x = getchar();
				if (x == 'x') {
						d = i;
						val[i] = 9;
				}else 
						val[i] = x - '0';
				getchar(); 
		}
		
		if (DBFS()) print();
		else puts("unsolvable");
		
		return 0;
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值