Poj 1077 Eight 八数码
题目描述:求八数码的解,输出x的移动方式(输出步数最少的解,但是也可能会有多解,所以是special judge)
如果判断8数码有没有解可以用逆序数求,找出规律即可求解
解法一:搜索(没写过)
解法二:康托展开,一种hash的方法。
int try_to_insert(int s){
int code = 0;
for(int i=0;i<9;i++){
int cnt=0;
for(int j=i+1;j<9;j++){
if(st[s][j]<st[s][i]) cnt++;
}
code += cnt*fact[8-i];
}
if(vis[code]==1) return 0;
return vis[code] = 1;
}
如果简单的开一个数组,判重的时候后则需要开一个,则需要开一个九维的数组,一共会耗去99=387420789项,但其实0~8的排列只有9!=362880个,所以可以用一个hash表一一对应起来。
解法3:A*(还不会)
View Code
1 Source Code
2
3 Problem: 1077 User: celia01
4 Memory: 8920K Time: 141MS
5 Language: G++ Result: Accepted
6
7 Source Code
8 #include<iostream>
9 #include<cstdio>
10 #include<cmath>
11 #include<cstring>
12 #include<algorithm>
13 #include<queue>
14 #define see(x) cout<<#x<<":"<<x<<endl;
15 using namespace std;
16 typedef int State[9];
17 const int MAXSIZE = 1000000;
18 State st[MAXSIZE], goal;
19
20 const int dx[] = {0,-1,0,1};
21 const int dy[] = {-1,0,1,0};
22 bool vis[400000];
23 int fact[9];
24 int path[MAXSIZE];
25 int pre[MAXSIZE];
26 void init_lookup_table(){
27 memset(vis,0,sizeof(vis));
28 fact[0] = 1;
29 for(int i=1;i<9;i++){
30 fact[i] = fact[i-1]*i;
31 }
32 }
33 int try_to_insert(int s){
34 int code = 0;
35 for(int i=0;i<9;i++){
36 int cnt=0;
37 for(int j=i+1;j<9;j++){
38 if(st[s][j]<st[s][i]) cnt++;
39 }
40 code += cnt*fact[8-i];
41 }
42 if(vis[code]==1) return 0;
43 return vis[code] = 1;
44 }
45
46 int bfs(){
47 init_lookup_table();
48 int f=1, r=2;
49 while(f<r){
50 State& s = st[f];
51
52 if( memcmp(goal,s,sizeof(s)) == 0 ) return f;
53 int z;
54 for(z=0;z<9;z++) if(s[z]==0) break;
55 int x=z/3, y=z%3;
56 for(int d=0;d<4;d++){
57 int newx = x+dx[d];
58 int newy = y+dy[d];
59 int newz = newx*3+newy;
60 if(newx>=0&&newx<3&&newy>=0&&newy<3){
61 State &t = st[r];
62 memcpy(&t,&s,sizeof(s));
63 t[newz] = s[z];
64 t[z] = s[newz];
65 pre[r] = f;
66 path[r] = d;
67 if(try_to_insert(r)) r++;
68 }
69 }
70 f++;
71 }
72 return 0;
73 }
74
75 void Path(int r){
76 if(r<=1) return;
77 Path(pre[r]);
78 if(path[r]==0)
79 printf("l");
80 else if(path[r]==1)
81 printf("u");
82 else if(path[r]==2)
83 printf("r");
84 else
85 printf("d");
86 }
87 int main(){
88 int i, j, k, l;
89 char ch[3];
90 for(i=0;i<9;i++){
91 scanf("%s",ch);
92 if(ch[0]=='x'){
93 st[1][i] = 0;
94 }
95 else st[1][i] = ch[0]-'0';
96 goal[i]=i+1;
97 }
98 goal[8] = 0;
99
100 int ans = bfs();
101 if(ans>0) Path(ans);
102 else printf("-1");
103 puts("");
104 return 0;
105 }
View Code
1 Source Code
2
3 Problem: 1077 User: celia01
4 Memory: 12840K Time: 110MS
5 Language: G++ Result: Accepted
6
7 Source Code
8
9
10 #include<iostream>
11 #include<cstdio>
12 #include<cmath>
13 #include<cstring>
14 #include<algorithm>
15 #include<queue>
16 #define see(x) cout<<#x<<":"<<x<<endl;
17 using namespace std;
18 typedef int State[9];
19 const int MAXSIZE = 1000000;
20 State st[MAXSIZE], goal;
21 int dist[MAXSIZE];
22
23 const int dx[] = {0,-1,0,1};
24 const int dy[] = {-1,0,1,0};
25 bool vis[400000];
26 int fact[9];
27 int path[MAXSIZE];
28 int pre[MAXSIZE];
29 void init_lookup_table(){
30 memset(vis,0,sizeof(vis));
31 memset(dist,0,sizeof(dist));
32 fact[0] = 1;
33 for(int i=1;i<9;i++){
34 fact[i] = fact[i-1]*i;
35 }
36 }
37 int try_to_insert(int s){
38 int code = 0;
39 for(int i=0;i<9;i++){
40 int cnt=0;
41 for(int j=i+1;j<9;j++){
42 if(st[s][j]<st[s][i]) cnt++;
43 }
44 code += cnt*fact[8-i];
45 }
46 // see(vis[code])
47 if(vis[code]==1) return 0;
48 return vis[code] = 1;
49 }
50
51 int bfs(){
52 init_lookup_table();
53 int f=1, r=2;
54 while(f<r){
55 //see(f) see(r)
56 State& s = st[f];
57
58 if( memcmp(goal,s,sizeof(s)) == 0 ) return f;
59 int z;
60 for(z=0;z<9;z++) if(s[z]==0) break;
61 int x=z/3, y=z%3;
62 for(int d=0;d<4;d++){
63 // system("pause");
64 int newx = x+dx[d];
65 int newy = y+dy[d];
66 int newz = newx*3+newy;
67 // see(z) see(newz)
68 if(newx>=0&&newx<3&&newy>=0&&newy<3){
69 State &t = st[r];
70 memcpy(&t,&s,sizeof(s));
71 t[newz] = s[z];
72 t[z] = s[newz];
73 // dist[r] = dist[f]+1;
74 pre[r] = f;
75 path[r] = d;
76 if(try_to_insert(r)) r++;
77 }
78 }
79 f++;
80 // see(f)
81 }
82 return 0;
83 }
84
85 void Path(int r){
86 if(r<=1) return;
87 Path(pre[r]);
88 if(path[r]==0)
89 printf("l");
90 else if(path[r]==1)
91 printf("u");
92 else if(path[r]==2)
93 printf("r");
94 else
95 printf("d");
96 }
97 int main(){
98 int i, j, k, l;
99 char ch[3];
100 for(i=0;i<9;i++){
101 scanf("%s",ch);
102 if(ch[0]=='x'){
103 st[1][i] = 0;
104 }
105 else st[1][i] = ch[0]-'0';
106 goal[i]=i+1;
107 }
108 goal[8] = 0;
109 // for(i=0;i<9;i++) cout<<st[1][i]; cout<<endl;
110 // for(i=0;i<9;i++) cout<<goal[i]; cout<<endl;
111
112 int ans = bfs();//see(ans)
113 if(ans>0) Path(ans);
114 else printf("-1");
115 puts("");
116 return 0;
117 }