【搜索】hdu4457 Klotski_2012杭州赛区E题
http://acm.hdu.edu.cn/showproblem.php?pid=4457
这个题目在现在看到就发现是一个赤裸裸到暴搜题,比赛时候由于最后只剩下40分钟给我,最后只写完一个最基本到广搜,赛后听说隔壁到师兄双向广搜就pass了=。=~
今天看到决定把它切掉,一开始写了一个双向广搜,TLE了。之后仔细一想对于20*20的数据,如果每个块大小都只是1*1一共10个块如果没有剪,由于状态数太多是不可能通过到。简单试验一下果然10*10就无可救药了,于是重写了一个A*+卡节点的版本,简单的用曼哈顿距离和做启发函数,每层卡了5000个节点,4900ms险险通过。。
双向广搜
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<map> 6 #include<set> 7 #include<vector> 8 const int mm[4][2] = {0,1,0,-1,1,0,-1,0}; 9 using namespace std; 10 typedef long long LL; 11 12 struct Point{ 13 int x,y; 14 Point(int _x=0 , int _y=0 ):x(_x),y(_y){} 15 }st[10],ed[10]; 16 struct Node{ 17 Point g[10]; 18 int step; 19 Node( Point h[] ,int x ) { 20 memcpy( g , h , sizeof(g) ); 21 step = x; 22 } 23 Node() {} 24 }tmp; 25 queue<Node> que1,que2; 26 set<LL> ha1,ha2; 27 vector<Point> data[10]; 28 int n,m,K; 29 char s[25][25]; 30 int now[25][25]; 31 32 LL hash(Point x[] ) { 33 LL ret = 0; 34 for (int i = 0; i<K; i++) ret = (ret*10007+x[i].x)*10007+x[i].y; 35 return ret; 36 } 37 inline bool in_range(int x ,int y ) { 38 return x>=0 && x<n && y>=0 && y<m; 39 } 40 int solve() 41 { 42 for (int L = 1; !que1.empty() && !que2.empty(); L++ ) { 43 printf("%d\n" , L ); 44 while ( !que1.empty() ) { 45 if ( que1.front().step != L ) break; 46 tmp = que1.front(); que1.pop(); 47 memset( now , -1 , sizeof(now) ); 48 for (int i = 0; i<K; i++) 49 for(int j = 0; j<data[i].size(); j++) 50 now[data[i][j].x+tmp.g[i].x][data[i][j].y+tmp.g[i].y] = i; 51 // for (int i = 0; i<n; i++){ 52 // for (int j = 0; j<m; j++) printf("%c", now[i][j]==-1?'.':('0'+now[i][j] ) ); puts(""); 53 // } 54 for (int i = 0; i<K; i++) 55 for (int d = 0; d<4; d++ ){ 56 bool flag = true; 57 for (int j = 0; j<data[i].size(); j++ ) { 58 int x = data[i][j].x+tmp.g[i].x+mm[d][0] , y = data[i][j].y+tmp.g[i].y+mm[d][1]; 59 if ( !in_range(x,y) || now[x][y] != -1 && now[x][y] != i ) { flag = false; break; } 60 } 61 if ( flag ) { 62 Node k = tmp; 63 k.g[i].x += mm[d][0] , k.g[i].y += mm[d][1]; 64 k.step = tmp.step+1; 65 LL h = hash(k.g); 66 if ( ha1.find(h) != ha1.end() ) continue; 67 ha1.insert(h); que1.push(k); 68 if ( ha2.find(h) != ha2.end() ) return L*2-1; 69 } 70 } 71 } 72 while ( !que2.empty() ) { 73 if ( que2.front().step != L ) break; 74 tmp = que2.front(); que2.pop(); 75 memset( now , -1 , sizeof(now) ); 76 for (int i = 0; i<K; i++) 77 for(int j = 0; j<data[i].size(); j++) 78 now[data[i][j].x+tmp.g[i].x][data[i][j].y+tmp.g[i].y] = i; 79 for (int i = 0; i<K; i++) 80 for (int d = 0; d<4; d++ ){ 81 bool flag = true; 82 for (int j = 0; j<data[i].size(); j++ ) { 83 int x = data[i][j].x+tmp.g[i].x+mm[d][0] , y = data[i][j].y+tmp.g[i].y+mm[d][1]; 84 if ( !in_range(x,y) || now[x][y] != -1 && now[x][y] != i ) { flag = false; break; } 85 } 86 if ( flag ) { 87 Node k = tmp; 88 k.g[i].x += mm[d][0] , k.g[i].y += mm[d][1]; 89 k.step = tmp.step+1; 90 LL h = hash(k.g); 91 if ( ha2.find(h) != ha2.end() ) continue; 92 ha2.insert(h); que2.push(k); 93 if ( ha1.find(h) != ha1.end() ) return L*2; 94 } 95 } 96 } 97 } 98 return -1; 99 } 100 101 int main(){ 102 while ( ~scanf("%d%d%d", &n, &m, &K ) ) { 103 if ( n == 0 && m == 0 && K == 0 ) break; 104 for (int i = 0; i<n; i++) scanf("%s", s[i]); 105 for (int i = 0; i<K; i++) data[i].clear(); 106 for (int i = 0; i<K; i++ ) { 107 int g = n, h = m; 108 for(int x = 0; x<n; x++) for (int y = 0; y<m; y++ ) 109 if ( s[x][y] == '0'+i ) g = min(x,g),h = min(y,h); 110 for(int x = 0; x<n; x++) for (int y = 0; y<m; y++ ) 111 if ( s[x][y] == '0'+i ) data[i].push_back( Point(x-g,y-h) ); 112 st[i] = Point(g,h); 113 } 114 for (int i = 0; i<n; i++) scanf("%s", s[i]); 115 for (int i = 0; i<K; i++ ) { 116 int g = n, h = m; 117 for(int x = 0; x<n; x++) for (int y = 0; y<m; y++ ) 118 if ( s[x][y] == '0'+i ) g = min(x,g),h = min(y,h); 119 ed[i] = Point(g,h); 120 } 121 if ( hash(st) == hash(ed) ) { printf("%d\n" , 0 ); continue; } 122 ha1.clear(); 123 ha2.clear(); 124 ha1.insert(hash(st)); ha2.insert(hash(ed)); 125 while ( !que1.empty() ) que1.pop(); 126 while ( !que2.empty() ) que2.pop(); 127 que1.push( Node(st,1) ); 128 que2.push( Node(ed,1) ); 129 printf("%d\n" , solve() ); 130 } 131 return 0; 132 }
A*
//By Lin #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<map> #include<set> #include<vector> const int mm[4][2] = {0,1,0,-1,1,0,-1,0}; using namespace std; typedef long long LL; int n,m,K; struct Point{ int x,y; Point(int _x=0 , int _y=0 ):x(_x),y(_y){} }st[10],ed[10]; struct Node{ Point g[10]; int dis; Node( Point h[]) { memcpy( g , h , sizeof(g) ); dis = 0; for (int i = 0; i<K; i++) dis += abs(g[i].x-ed[i].x), dis += abs(g[i].y-ed[i].y); } Node() {} }tmp; Node que[2][100005]; int cnt[2]; set<LL> ha; vector<Point> data[10]; char s[25][25]; int now[25][25]; LL over; bool cmp( const Node &a , const Node &b ) { return a.dis < b.dis; } LL hash(Point x[] ) { LL ret = 0; for (int i = 0; i<K; i++) ret = (ret*10007+x[i].x)*10007+x[i].y; return ret; } inline bool in_range(int x ,int y ) { return x>=0 && x<n && y>=0 && y<m; } int solve() { for (int L = 1; cnt[L%2]; L++ ) { int g = L%2 , h = (L+1)%2; sort( que[g] , que[g]+cnt[g] , cmp ); if ( cnt[g] > 3000 ) cnt[g] = 3000; cnt[h] = 0; for (int i = 0; i<cnt[g]; i++ ) { tmp = que[g][i]; memset( now , -1 , sizeof(now) ); for (int i = 0; i<K; i++) for(int j = 0; j<data[i].size(); j++) now[data[i][j].x+tmp.g[i].x][data[i][j].y+tmp.g[i].y] = i; // for (int i = 0; i<n; i++){ // for (int j = 0; j<m; j++) printf("%c", now[i][j]==-1?'.':('0'+now[i][j] ) ); puts(""); // } for (int i = 0; i<K; i++) for (int d = 0; d<4; d++ ){ bool flag = true; for (int j = 0; j<data[i].size(); j++ ) { int x = data[i][j].x+tmp.g[i].x+mm[d][0] , y = data[i][j].y+tmp.g[i].y+mm[d][1]; if ( !in_range(x,y) || now[x][y] != -1 && now[x][y] != i ) { flag = false; break; } } if ( flag ) { Node k = tmp; k.g[i].x += mm[d][0] , k.g[i].y += mm[d][1]; LL hh = hash(k.g); if ( ha.find(hh) != ha.end() ) continue; ha.insert(hh); que[h][cnt[h]++] = Node(k.g); if ( hh == over ) return L; } } } } return -1; } int main(){ while ( ~scanf("%d%d%d", &n, &m, &K ) ) { if ( n == 0 && m == 0 && K == 0 ) break; for (int i = 0; i<n; i++) scanf("%s", s[i]); for (int i = 0; i<K; i++) data[i].clear(); for (int i = 0; i<K; i++ ) { int g = n, h = m; for(int x = 0; x<n; x++) for (int y = 0; y<m; y++ ) if ( s[x][y] == '0'+i ) g = min(x,g),h = min(y,h); for(int x = 0; x<n; x++) for (int y = 0; y<m; y++ ) if ( s[x][y] == '0'+i ) data[i].push_back( Point(x-g,y-h) ); st[i] = Point(g,h); } for (int i = 0; i<n; i++) scanf("%s", s[i]); for (int i = 0; i<K; i++ ) { int g = n, h = m; for(int x = 0; x<n; x++) for (int y = 0; y<m; y++ ) if ( s[x][y] == '0'+i ) g = min(x,g),h = min(y,h); ed[i] = Point(g,h); } if ( hash(st) == hash(ed) ) { printf("%d\n" , 0 ); continue; } over = hash(ed); ha.clear(); ha.insert(hash(st)); cnt[1] = 0; que[1][cnt[1]++] = Node(st); printf("%d\n" , solve() ); } return 0; }