Seven Puzzle
Time Limit : 1 sec, Memory Limit : 65536 KB
7パズルは8つの正方形のカードとこれらのカードがぴたりと収まる枠を使って行います。それぞれのカードは互いに区別できるように、0,1,2....7と番号がつけられています。枠には、縦に2個、横に4個のカードを並べることができます。
7パズルを始めるときには、まず枠にすべてのカードを入れます。枠のなかで0のカードだけは、上下左右に隣接するカードと位置を交換することができます。たとえば、枠の状態が図( a )のときに、0のカードの右に隣接した、7のカードと位置を交換すれば、図( b )の状態になります。あるいは、図( a )の状態から0のカードの下に隣接した2のカードと位置を交換すれば図( c )の状態になります。カードの位置を入れ替える操作はこれだけが許されます。図( a )の状態で0のカードと上下左右に隣接するカードは7と2のカードだけなので、これ以外の位置の入れ替えは許されません。
ゲームの目的は、カードをきれいに整列して図( d )の状態にすることです。最初の状態を入力とし、カードをきれいに整列するまでに、必要な最小手数を出力して終了するプログラムを作成してください。ただし、入力されたカードの状態からは図( d )の状態に移ることは可能であるとします。
入力データは、1行に8つの数字が与えられます。これらは、最初の状態のカードの並びを表します。図( a )の数字表現は0,7,3,4,2,5,1,6に、図( c )は2,7,3,4,0,5,1,6となります。
図( a ) 0,7,3,4,2,5,1,6の場合 | 図( b ) 7,0,3,4,2,5,1,6の場合 |
---|
図( c ) 2,7,3,4,0,5,1,6の場合 | 図( d ) 0,1,2,3,4,5,6,7(最終状態) |
---|
Input
1つ目のパズルの状態(整数;空白区切り) 2つ目のパズルの状態(整数;空白区切り) : :
与えられるパズルの数は1000以下です。
Output
1つ目のパズルの状態から最終状態へ移行する最小手数(整数) 2つ目のパズルの状態から最終状態へ移行する最小手数(整数) : :
Sample Input
0 1 2 3 4 5 6 7 1 0 2 3 4 5 6 7 7 6 5 4 3 2 1 0
Output for the Sample Input
0 1 28 题意:给个初始状态为0-7的一个排列,0表示空格。可以挪动空格周围的数字,最后使得最终状态为0-7顺序排列。 分析:就是类似八数码的问题。之前没做过八数码的题。 记录下思考过程。首先很容易想到就是从初始状态开始搜索出最终状态,每次的策略就是移动0周围的数字。但,怎么表示状态呢?这8个格子不是可以看成矩阵用二维数组记录吗?于是。。。 1、可以用一个结构体,结构体中有一个二维数组来记录,另一个变量记录初始状态搜到的步数2、结构体中的数组可以用一维数组,这样策略就是0所在的位置p与p+1、p-1、p+4、p-4四个位置的元素交换,当然交换的pos位置必须在0-7范围内,且 换行的地方要注意!!!p=3时,pos=4是不行的p=4时,pos=3是不行的 然后就是bfs搜了。状态有8!(8个数全排列)= 40320 开始用的sum(a[i]*i)来hash,总是从7 6 5 4 3 2 1 0搜不到目标状态。后来意识到是hash的时候有重复造成的错误! 于是看了下康托展开:http://zh.wikipedia.org/wiki/%E5%BA%B7%E6%89%98%E5%B1%95%E5%BC%80康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。 于是改写了hash方法后,能过样例了。。。但是tle于是把之前所有用vector的地方都改成了手写数组int a[8]。。还是tle 于是想到预处理,从0 1 2 3 4 5 6 7这个排列作初始状态出发来搜,hash[i]记录到达i对应的排列的步数n位(0~n-1)全排列后,其康托展开唯一且最大约为n!,因此可以由更小的空间来储存这些排列。所以hash数组只要开8!+1=40321即可!OK!
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #include<set> 11 12 using namespace std; 13 14 typedef long long ll; 15 16 struct node 17 { 18 int sta[8]; 19 int step; 20 int p; 21 }; 22 queue<node> q; 23 int s[8]; 24 25 int d[] = {-4,-1,1,4}; 26 int hash[40321]; 27 int w[10],vec[10]; 28 29 void init() 30 { 31 w[0] = 1; 32 int sum = 1; 33 for(int i=1;i<=7;i++) 34 { 35 sum*=i; 36 w[i] = sum; 37 } 38 } 39 40 void solve() 41 { 42 while(!q.empty()) q.pop(); 43 memset(hash,-1,sizeof(hash)); 44 45 node ff,gg,hh; 46 for(int i=0;i<8;i++) 47 ff.sta[i] = i; 48 ff.step = 0; 49 50 51 int mark = 0,pos; 52 int n = 8; 53 for(int i=0;i<n;i++) 54 { 55 int cnt = 0; 56 for(int j=i+1;j<n;j++) 57 { 58 if(s[j]<s[i]) cnt++; 59 } 60 vec[n-i-1] = cnt; 61 } 62 for(int i=0;i<n;i++) 63 mark += vec[i]*w[i]; 64 mark++; 65 ff.p = mark; 66 q.push(ff); 67 hash[mark] = 0; 68 69 int cur[8],next[8]; 70 while(!q.empty()) 71 { 72 gg = q.front(); 73 q.pop(); 74 memcpy(cur,gg.sta,sizeof(gg.sta)); 75 int step = gg.step; 76 77 for(int i=0;i<8;i++) 78 { 79 if(cur[i] == 0) 80 { 81 pos = i; 82 break; 83 } 84 } 85 86 for(int i=0;i<4;i++) 87 { 88 int x = pos+d[i]; 89 if(x<0 || x>7) continue; 90 if(x==3 && pos==4) continue; 91 if(x==4 && pos==3) continue; 92 93 memcpy(next,cur,sizeof(cur)); 94 95 int tmp = next[x]; 96 next[x] = next[pos]; 97 next[pos] = tmp; 98 99 int mark = 0; 100 for(int k=0;k<8;k++) 101 { 102 int cnt = 0; 103 for(int j=k+1;j<8;j++) 104 { 105 if(next[j]<next[k]) cnt++; 106 } 107 vec[n-k-1] = cnt; 108 } 109 for(int k=0;k<8;k++) 110 mark += vec[k]*w[k]; 111 mark++; 112 if(hash[mark]!=-1) continue; 113 114 memcpy(hh.sta,next,sizeof(next)); 115 hh.step = step+1; 116 hh.p = mark; 117 q.push(hh); 118 hash[mark] = hh.step; 119 } 120 } 121 } 122 123 int main() 124 { 125 // freopen("1.txt","w",stdout); 126 127 init(); 128 solve(); 129 int x; 130 while(~scanf("%d",&s[0])) 131 { 132 for(int i=1;i<=7;i++) 133 { 134 scanf("%d",&x); 135 s[i] = x; 136 } 137 int omg = 0; 138 for(int i=0;i<8;i++) 139 { 140 int cnt = 0; 141 for(int j=i+1;j<8;j++) 142 { 143 if(s[j]<s[i]) 144 cnt++; 145 } 146 vec[8-1-i] = cnt; 147 } 148 for(int i=0;i<8;i++) 149 omg += vec[i]*w[i]; 150 omg++; 151 printf("%d\n",hash[omg]); 152 } 153 return 0; 154 }
时间: 2024-10-27 05:52:04