搜索_IDA*_POJ2286_The Rotation Game

版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84428319

点此打开题目页面

思路分析:

    考虑使用IDA*, 设当前格局(棋盘)中心区域出现次数最多的数的出现次数为m, 显然m <= 8, 易知每次旋转变换至多使得m的值增加1, 因此将8 - m作为估价函数. 基于此策略给出如下AC代码:

//POJ2286_The Rotation Game
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int lpos[7] = {1, 3, 7, 12, 16, 21, 23}, rpos[7] = {2, 4, 9, 13, 18, 22, 24}
	  , upos[7] = {5, 6, 7, 8, 9, 10, 11}, dpos[7] = {14, 15, 16, 17, 18, 19, 20};
struct State{
	char l[8], r[8], u[8], d[8];
	//根据输入数组arr初始化l, r, u, d, arr[1]为第一个有效元素 
	void init(const int *arr){
		for(int i = 0; i < 7; ++i) 
			l[i + 1] = arr[lpos[i]], r[i + 1] = arr[rpos[i]]
			, u[i + 1] = arr[upos[i]], d[i + 1] = arr[dpos[i]];
	} 
	//返回中间出现次数最多的元素的出现次数
	int f() const{
		int arr[4]; memset(arr, 0, sizeof(arr)); 
		for(int i = 3; i <= 5; ++i) ++arr[l[i]], ++arr[r[i]]; ++arr[u[4]], ++arr[d[4]]; 
		int res = 0; for(int i = 1; i <= 3; ++i) res = max(res, arr[i]); return 8 - res;	
	}
	//根据dir(为A, B, C, D, E, F, G或H)执行对应的旋转操作 
	void move(char dir){
		if(dir == 'A') moveHelp(l, true, u, d, 3, 3, 5);
		else if(dir == 'B') moveHelp(r, true, u, d, 5, 3, 5);
		else if(dir == 'C') moveHelp(u, false, l, r, 3, 3, 5);
		else if(dir == 'D') moveHelp(d, false, l, r, 5, 3, 5);
		else if(dir == 'E') moveHelp(r, false, u, d, 5, 3, 5);
		else if(dir == 'F') moveHelp(l, false, u, d, 3, 3, 5);
		else if(dir == 'G') moveHelp(d, true, l, r, 5, 3, 5);
		else moveHelp(u, true, l, r, 3, 3, 5);
	}
	//将a(为l, r, u或d)左移(left为true)或右移(left为false), 并将b[bcpos]赋值为a[abpos],
	//将c[bcpos]赋值为a[acpos] 
	void moveHelp(char *a, bool left, char *b, char *c, int bcpos, int abpos, int acpos){
		char arr[16]; int si = sizeof(char) * 7; 
		memcpy(arr + 1, a + 1, si), memcpy(arr + 8, a + 1, si);
		if(!left) memcpy(a + 1, arr + 7, si); else memcpy(a + 1, arr + 2, si);
		b[bcpos] = a[abpos], c[bcpos] = a[acpos];
	}
};
int rp[200], deep, resNum; vector<char> respath;
const char rdir[8] = {'A', 'F', 'B', 'E', 'C', 'H', 'D', 'G'};
bool dfs(const State &sta, vector<char> &path){ 
	int f = sta.f();
	if(path.size() + f > deep) return false;
	if(!f){
		resNum = sta.l[3], respath = path;
		return true;
	}
	for(int i = 'A'; i <= 'H'; ++i){
		if(!path.empty() && (rp[path.back()] ^ 1) == rp[i]) continue;
		State tmp = sta; tmp.move(i), path.push_back(i);
		if(dfs(tmp, path)) return true;
		path.pop_back();
	}
	return false;
}
int main(){
	int arr[25]; 
	rp['A'] = 0, rp['F'] = 1, rp['B'] = 2, rp['E'] = 3
	, rp['C'] = 4, rp['H'] = 5, rp['D'] = 6, rp['G'] = 7;
	while(scanf("%d", &arr[1]), arr[1]){
		for(int i = 2; i <= 24; ++i) scanf("%d", &arr[i]);
		State beg; beg.init(arr); 
		if(!beg.f()){
			cout << "No moves needed" << endl << (int)beg.l[3] << endl; continue;
		}
		vector<char> path; deep = 0, respath.clear(); 
		while(path.clear(), !dfs(beg, path)) ++deep;
		for(int i = 0; i < respath.size(); ++i) cout << respath[i]; cout << endl;
		cout << resNum << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/solider98/article/details/84428319