【搜索】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;
}
posted @ 2012-11-20 00:07  lzqxh  阅读(328)  评论(0编辑  收藏  举报