題目:如題目的圖示給你一個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