hdu 3295 广搜 状态压缩

题意:一个棋盘,0表示没放棋子,1 2 3 4表示放了该颜色的棋子,每次选择一个棋子消掉,同时跟它相连的同色棋子也会被消掉,消掉棋子后形成空格0,空格上方的棋子会掉下来,填补空格。如果某列全为0,右边整体向左移,填补空列。

分析:广搜 0ms

每行最多6个数,每个数为0~4,将其转化成一个6位数。 最多6行,所以一个状态需要6个数来保存,这里我用了一个长度为6的一维数组。。

每次从队列里取出一个状态,将其还原到二维数组里,取某棋子消掉,按要求填补空格得到新的二维数组,再将新数组进行压缩,入队列。

 

 

int dx[] = {-1,0,1,0};//up Right down Left
int dy[] = {0,1,0,-1};

const int N = 6;
int a[N][N+1], b[N][N], temp[N][N];
int n, m, cnt, ans;

struct node{
    int a[N], d;
}u, v;

queue<node> q;

bool code(int *c){//将数组a[i][]编码成c[i]
    bool flag = true;
    FOR(i, 0, n) {
        c[i] = 0;
        FOR(j, 0, m) c[i] = c[i]*5+a[i][j];
        if(c[i]) flag = false;
    }
    return flag;
}

void decode(int *c){//将c[i]中的数还原成数组a[i][]
    FOR(i, 0, n) FOD(j, m-1, 0){
        a[i][j] = c[i]%5; c[i] /= 5;
    }
}

int t;
void dfs(int x, int y){
    FOR(i, 0, 4){
        int xx=x+dx[i], yy=y+dy[i];
        if(xx<0 || yy<0 || xx==n || yy==m) continue;
        if(a[xx][yy]==t && b[xx][yy]==0) {
            b[xx][yy]=cnt;
            dfs(xx, yy);
        }
    }
}

int tt[N];
void remove(int x, int y){
    t = a[x][y];
    b[x][y] = ++cnt;
    dfs(x, y);//深搜确定和a[x][y]相同且连通的部分

    FOR(j, 0, m){//某列被去掉了一部分,剩余的下移
        int p = 0;
        FOD(i, n-1, 0) {
            if(a[i][j] == 0) break;
            if(b[i][j]!=cnt) tt[p++] = a[i][j];
        }
        FOR(i, 0, p) a[n-1-i][j] = tt[i];
        FOR(i, 0, n-p) a[i][j] = 0;
    }

    FOR(j, 0, m) //某列都为0,右边的左移
        if(a[n-1][j]==0)
            FOR(jj, j, m-1)
                FOR(i, 0, n)
                    a[i][jj] = a[i][jj+1];
}

void bfs(){
    code(u.a); u.d=0;
    while(!q.empty()) q.pop(); q.push(u);
    while(!q.empty()){
        u = q.front(); q.pop();
        decode(u.a);
        FOR(i, 0, n) FOR(j, 0, m) b[i][j] = 0, temp[i][j] = a[i][j];
        cnt = 0;
        FOR(j, 0, m){
            FOD(i, n-1, 0){
                if(a[i][j]==0) break;
                if(b[i][j] ) continue;
                remove(i, j);   //把和ij相同的去掉
                v.d = u.d+1;
                if( code(v.a) )  { ans = v.d; return;}
                q.push(v);
                FOR(ii, 0, n) FOR(jj, 0, m) a[ii][jj] = temp[ii][jj];
            }
        }
    }
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    #endif

    while(~scanf("%d%d", &n, &m)){
        FOR(i, 0, n) FOR(j, 0, m) scanf("%d", &a[i][j]);

        ans = 0;
        bfs();
        printf("%d\n", ans);
    }

    return 0;
}

 

posted @ 2013-05-29 18:11  心向往之  阅读(276)  评论(0编辑  收藏  举报