1. 程式人生 > >【[HAOI2008]移動玩具】

【[HAOI2008]移動玩具】

-o pan map 狀態 print scan etc push 行操作

並不知道省選考這種爆搜題有什麽意義。。

正文部分:

觀察題目中只有12個數,每個數只有0和1,明顯所以狀態的數量為\(2^{12}=4096\),那豈不是爆搜隨便做?
對於1個狀態hash:
我們將現在這12位數打包成一個字符串,用\(map\)記錄一下這個字符串是否出現過。

對於1個狀態的unhash,我們將這個字符串轉到1個矩陣裏,就是當前的狀態。
於是我們就可以輕松的得到每種情況的狀態。
對於Bfs過程,我們對unhash完的矩陣進行操作,每次選取其中為1的點,分4個方向向外擴散,然後壓成1個新的狀態,如此繼續。

My Code:

// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define il inline
#define gc getchar
using namespace std;
string S,T;
char x;
map<string,bool> vis;
int n,m,i,j,k;
int dir[4][2] = {{0,-1},{0,1},{-1,0},{1,0}};
int tmp[5][5];
struct Bfs {
    string zt;int step;
};
il int read() {
    int res = 0;char c;bool sign = 0;
    for(c = gc();!isdigit(c);c = gc()) sign |= c == ‘-‘;
    for(;isdigit(c);c = gc()) res = (res << 1) + (res << 3) + (c ^ 48);
    return sign ? -res : res;
}  
il void unhash(string s,int a[5][5]) {
    int i,j,id = 0;
    for(i = 1;i <= 4;i++) {
        for(j = 1;j <= 4;j++) {
            a[i][j] = s[id];id++;
        }
    }
    return;
}
il string hash(int a[5][5]) {
    int i,j;string res = "";
    for(i = 1;i <= 4;i++) {
        for(j = 1;j <= 4;j++) {
            res += a[i][j];
        }
    }return res;
}
il void print(int a[5][5]) {
    int i,j;
    for(i = 1;i <= 4;i++) {
        for(j = 1;j <= 4;j++) {
            printf("%d%c",a[i][j],j == n ? ‘\n‘ : ‘ ‘);
        }   
    }
}
il void bfs(string s,string t) {
    queue<Bfs> Q;while(!Q.empty()) Q.pop();
    Q.push((Bfs){s,0});vis[s] = 1;
    while(!Q.empty()) {
        string zt = Q.front().zt;int step = Q.front().step;
        Q.pop();
        if(zt == T) {
            printf("%d",step);
            exit(0);
        }
        unhash(zt,tmp);int i,j,k;
    //  print(tmp);
        for(i = 1;i <= 4;i++) {
            for(j = 1;j <= 4;j++) {
                if(!tmp[i][j]) continue;
                for(k = 0;k < 4;k++) {
                    int nx = i + dir[k][0];
                    int ny = j + dir[k][1];
                    if(nx < 1 || nx > 4 || ny < 1 || ny > 4) continue;
                    if(tmp[nx][ny]) continue;
                    tmp[nx][ny] = 1;tmp[i][j] = 0;
                    string new_zt = hash(tmp);
                    if(!vis[new_zt]) {
                        vis[new_zt] = 1;
                        Q.push((Bfs){new_zt,step + 1});
                    }
                    tmp[nx][ny] = 0;tmp[i][j] = 1;
                }
            }
        }
    }
}
int main() { S = T = "";
    for(i = 1;i <= 4;i++) {
        for(j = 1;j <= 4;j++) {
            scanf("%c",&x);
            while(!isdigit(x)) scanf("%c",&x);
            S += x - 48;
        }
    }
    for(i = 1;i <= 4;i++) {
        for(j = 1;j <= 4;j++) {
            scanf("%c",&x);
            while(!isdigit(x)) scanf("%c",&x);
            T += x - 48;
        }
    }   
    bfs(S,T);   
    return 0;
}

【[HAOI2008]移動玩具】