UVa 10422 - Knights in FEN

題目:如題目的圖示給你一個5*5的棋盤上面有12個黑騎士和12個白騎士和一個空格;

現在要你從一個給定狀態變成目標狀態,每一可以移動一個騎士(走日字,國際象棋);

問多少步能走到目標狀態,超過10步輸出超過10步走到。

目標狀態:

分析:搜索,狀態壓縮,哈希表。用一個25位的01串可以表示任意一種狀態(空格用0表示(也可用1),避免當做兩種狀態);

所以每個狀態可以用一個int類型的數據表示,然後計算出個狀態的到達關係,bfs即可。

搜索時使用hash函數壓縮數據(頭則內存不夠)。

說明:大年三十的刷道題╮(╯▽╰)╭。

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>

using namespace std;

char in[5][6];
int  dxy[8][2] = {-2,-1,-2,1,2,-1,2,1,-1,-2,-1,2,1,-2,1,2};
int  jump[25][8];

typedef struct _d_node
{
	int value;
	int space;
	int steps;
}_data_node;

//hash_list_begin
typedef struct _h_node
{
	_data_node 	data;
	_h_node* 	next;
}_hash_node;
_hash_node 	_hash_list[100000];
_hash_node *_hash_head[100000];
int         _hash_size;

void hash_init(void)
{
	_hash_size = 0;
	memset(_hash_head, 0 , sizeof(_hash_head));
	memset(_hash_list, 0 , sizeof(_hash_list));
}

int hash_find(_data_node v)
{
	int value = v.value%100000;
	for (_hash_node* p = _hash_head[value] ; p ; p = p->next)
		if (p->data.value == v.value && p->data.space == v.space)
			return 1;
	return 0;
}

void hash_add(_data_node v)
{
	int value = v.value%100000;
	_hash_list[_hash_size].data = v;
	_hash_list[_hash_size].next = _hash_head[value];
	_hash_head[value] = &_hash_list[_hash_size ++];
}
//hash_list_end

//测试用输出函数
void show(_data_node a)
{
	printf("%2d:%2d\n",a.space,a.steps);
	int temp[32],save = 0;
	for (int i = 0 ; i < 32 ; ++ i)
		temp[i] = 0;
	int count = 0;
	while (a.value) {
		count += temp[save ++] = a.value%2;
		a.value /= 2;
	}
	for (int i = 0 ; i < 25 ; ++ i) {
		if (a.space == i) printf(" ");
		else printf("%d",temp[i]);
		if ((i+1)%5 == 0) printf("\n");
	}
}

_data_node Q[100000];
void bfs(_data_node s, _data_node t)
{
	if (s.value == t.value && s.space == t.space) {
		printf("Solvable in 0 move(s).\n");
		return;
	}

	hash_init();

	int move = 0,save = 0;
	Q[save ++] = s;
	hash_add(s);

	while (move < save) {
		_data_node New,now = Q[move ++];
		for (int k = 0 ; k < 8 ; ++ k) {
			if (jump[now.space][k] == -1) continue;
			New.steps = now.steps + 1;
			if (New.steps > 10) {
				printf("Unsolvable in less than 11 move(s).\n");
				return;
			}
			New.space = jump[now.space][k];
			New.value = now.value&((1<<25)-1-(1<<New.space));
			New.value = New.value|((((now.value&(1<<New.space)))>0)<<now.space);

			if (!hash_find(New)) {
				if (New.value == t.value && New.space == t.space) {
					printf("Solvable in %d move(s).\n",New.steps);
					return;
				}
				Q[save ++] = New;
				hash_add(New);
			}
		}
	}
} 

int main()
{
	//定义目标位置
	_data_node t;
		t.value = (8<<16)+(99<<8)+223;
		t.space = 12;
	//定义走法映射
	for (int i = 0 ; i < 5 ; ++ i)
	for (int j = 0 ; j < 5 ; ++ j)
	for (int k = 0 ; k < 8 ; ++ k) {
		int x = i+dxy[k][0];
		int y = j+dxy[k][1];
		if (x >= 0 && x < 5 && y >= 0 && y < 5)
			jump[5*i+j][k] = 5*x+y;
		else jump[5*i+j][k] = -1;
	}

	int n;
	while (~scanf("%d",&n) && n) {
		getchar();
		while (n --) {
			for (int i = 0 ; i < 5 ; ++ i)
				gets(in[i]);
			_data_node s;
				s.value = s.steps = 0;
			for (int i = 0 ; i < 5 ; ++ i)
			for (int j = 0 ; j < 5 ; ++ j)
				if (in[i][j] != ' ')
					s.value += (in[i][j]-'0')<<(i*5+j);
				else s.space = (i*5+j);

			bfs(s, t);
		}
	}
    return 0;
}
时间: 2024-10-16 12:30:18

UVa 10422 - Knights in FEN的相关文章

UVA Knights in FEN

题目如下: Problem D Knights in FEN Input: standard input Output: standard output Time Limit: 10 seconds There are black and white knightson a 5 by 5 chessboard. There are twelve of each color, and there is one squarethat is empty. At any time, a knight c

UVA 1364 - Knights of the Round Table(双连通+二分图判定)

UVA 1364 - Knights of the Round Table 题目链接 题意:有n个圆桌骑士,知道一些骑士互相憎恨,现在要开圆桌会议,每次最少3个人,必须是奇数人数,并且互相憎恨的骑士不能在相邻,问有多少骑士是一次都无法参加的 思路:把每个骑士可以相邻的连边,然后做双连通分量,然后对于每个连通分量,利用二分图染色判定去判断是否是奇圈 代码: #include <cstdio> #include <cstring> #include <vector> #in

UVA 1364 - Knights of the Round Table (找双连通分量 + 二分图染色法判断)

都特么别说话,我先A了这道题! 卧槽啊.....! 题意来自 kuangbin: 亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突, 并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求: 1.  相互憎恨的两个骑士不能坐在直接相邻的2个位置: 2.  出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果. 注意:1.所给出的憎恨关系一定是双向的,不存在单向憎恨关系. 2.由于是圆桌会议,则每个出席的骑士身边必定刚好有2个骑士. 即每个骑士的座位两边都

UVA题目分类

题目 Volume 0. Getting Started 开始10055 - Hashmat the Brave Warrior 10071 - Back to High School Physics 10300 - Ecological Premium 458 - The Decoder 494 - Kindergarten Counting Game 414 - Machined Surfaces 490 - Rotating Sentences 445 - Marvelous Mazes

UVA 11292 Dragon of Loowater(简单贪心)

Problem C: The Dragon of Loowater Once upon a time, in the Kingdom of Loowater, a minor nuisance turned into a major problem. The shores of Rellau Creek in central Loowater had always been a prime breeding ground for geese. Due to the lack of predato

uva 11292

A - Dragon of Loowater Time Limit:1000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVA 11292 Appoint description:  System Crawler  (2014-11-26) Description Problem C: The Dragon of Loowater Once upon a time, in the K

UVA之11292 Dragon of Loowater

Problem C: The Dragon of Loowater Once upon a time, in the Kingdom of Loowater, a minor nuisance turned into a major problem. The shores of Rellau Creek in central Loowater had always been a prime breeding ground for geese. Due to the lack of predato

·UVa」 11292 - Dragon of Loowater( 贪心 )

Problem C: The Dragon of Loowater Once upon a time, in the Kingdom of Loowater, a minor nuisance turned into a major problem. The shores of Rellau Creek in central Loowater had always been a prime breeding ground for geese. Due to the lack of predato

UVA它11292 - Dragon of Loowater

Problem C: The Dragon of Loowater Once upon a time, in the Kingdom of Loowater, a minor nuisance turned into a major problem. The shores of Rellau Creek in central Loowater had always been a prime breeding ground for geese. Due to the lack of predato