[ZOJ 3814 Sawtooth Puzzle] bfs+状态压缩

来源:互联网 发布:行业评选网络投票 编辑:程序博客网 时间:2024/05/17 18:47

题目

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3814

分析

可以发现对于两个相邻的格子并且他们相邻的边都是有锯齿的,那么他们的旋转的。进一步可以得知他们的影响关系如果出现循环也不会有矛盾,因此可以简单模拟旋转过程。

易知每个格子最多有四种状态,我们可以用4^9来表示所有的状态,然后暴力搜索,模拟其中的旋转过程就可以了。

注意一个地方,就是目标状态的判断。因为不同状态表示的实际格子状态可能是相同的,对目标状态九个格子要分别判断哪些压缩后的状态是合法的,只要出现一种合法状态就找到了解。

代码

#include<cstring>#include<string>#include<cstdio>#include<cstdlib>#include<iostream>#include<vector>#include<algorithm>#include<cmath>#include<queue>using namespace std;#define ll long long#define pf printf#define sf scanf#define Fill(a,b) memset(a,b,sizeof(a))struct State{    int st[11];    State(){}    State(int a1,int a2,int a3,int a4,int a5,int a6,int a7,int a8,int a9)    {        st[1] = a1; st[2] = a2; st[3] = a3; st[4] = a4; st[5] = a5; st[6] = a6; st[7] = a7; st[8] = a8; st[9] = a9;    }};queue<State>q;string s[10][10],t[10][10],p[10];int st[11][11];int tp[5][5];bool sol[11];bool cor[11][11];int f[1 << 20];int ans;const int up[] = {0,0,0,0,1,2,3,4,5,6};const int down[] = {0,4,5,6,7,8,9,0,0,0};const int lef[] = {0,0,1,2,0,4,5,0,7,8};const int rig[] = {0,2,3,0,5,6,0,8,9,0};inline void Init_initial(){    for (int i = 1; i <= 8; i++)        for (int j = 1; j <= 3; j++) cin>>s[j][i];    for (int i = 1; i <= 8; i++)        for (int j = 4; j <= 6; j++) cin>>s[j][i];    for (int i = 1; i <= 8; i++)        for (int j = 7; j <= 9; j++) cin>>s[j][i];}inline void Init_target(){    for (int i = 1; i <= 8; i++)        for (int j = 1; j <= 3; j++) cin>>t[j][i];    for (int i = 1; i <= 8; i++)        for (int j = 4; j <= 6; j++) cin>>t[j][i];    for (int i = 1; i <= 8; i++)        for (int j = 7; j <= 9; j++) cin>>t[j][i];}inline int trans(State x){    int ans = 0;    for (int i = 1; i <= 9; i++) ans = ans + (x.st[i] << (2 * (i - 1)));    return ans;}inline bool meshed(State x,int a,int e1,int b,int e2){    int f1 = st[a][tp[x.st[a]][e1]],f2 = st[b][tp[x.st[b]][e2]];    return (f1 == 1 && f2 == 1);}inline State rotate(State x,int y,int flag){    sol[y] = 1;    int l = lef[y],r = rig[y],u = up[y],d = down[y];    bool fl = 0,fu = 0,fd = 0,fr = 0;    if (l != 0 && !sol[l] && meshed(x,l,3,y,1)) fl = 1;    if (r != 0 && !sol[r] && meshed(x,r,1,y,3)) fr = 1;    if (u != 0 && !sol[u] && meshed(x,u,4,y,2)) fu = 1;    if (d != 0 && !sol[d] && meshed(x,d,2,y,4)) fd = 1;    int z = x.st[y];    if (flag == 1)    {        z = z + 1;        if (z == 4) z = 0;    }    else    {        z = z - 1;        if (z == -1) z = 3;    }    x.st[y] = z;    if (fl && !sol[l])    {        sol[l] = 1;        x = rotate(x,l,3 - flag);    }    if (fr && !sol[r])    {        sol[r] = 1;        x = rotate(x,r,3 - flag);    }    if (fu && !sol[u])    {        sol[u] = 1;        x = rotate(x,u,3 - flag);    }    if (fd && !sol[d])    {        sol[d] = 1;        x = rotate(x,d,3 - flag);    }    return x;}inline bool ok(State y){    for (int i = 1; i <= 9; i++)        if (!cor[i][y.st[i]]) return 0;    return 1;}inline void bfs(State x){    while (!q.empty()) q.pop();    q.push(x);    while (!q.empty())    {        x = q.front(); q.pop(); int sx = trans(x);        for (int i = 1; i <= 9; i++)        {            Fill(sol,0);            State y = rotate(x,i,1);            int sy = trans(y);            if (f[sy] > f[sx] + 1)            {                f[sy] = f[sx] + 1;                if (ok(y))                {                    ans = f[sy];                    return;                }                q.push(y);            }        }    }}inline bool same(int x){    for (int i = 1; i <= 8; i++)        for (int j = 0; j < 8; j++) if (s[x][i][j] != t[x][i][j]) return 0;    return 1;}inline void change(int x){    for (int i = 1; i <= 8; i++) p[i] = "";    for (int i = 1; i <= 8; i++)        for (int j = 8; j >= 1; j--) p[i] = p[i] + s[x][j][i - 1];    for (int i = 1; i <= 8; i++) s[x][i] = p[i];}int main(){   // freopen("in.txt","r",stdin);    int T; sf("%d",&T);    for (int TT = 1; TT <= T; TT++)    {        Init_initial();        Init_target();        for (int i = 1; i <= 9; i++)            for (int j = 1; j <= 4; j++) sf("%d",&st[i][j]);        Fill(f,63);        tp[0][1] = 1; tp[0][2] = 2; tp[0][3] = 3; tp[0][4] = 4;        tp[1][1] = 4; tp[1][2] = 1; tp[1][3] = 2; tp[1][4] = 3;        tp[2][1] = 3; tp[2][2] = 4; tp[2][3] = 1; tp[2][4] = 2;        tp[3][1] = 2; tp[3][2] = 3; tp[3][3] = 4; tp[3][4] = 1;        f[0] = 0;        ans = -1;        Fill(cor,0);        for (int i = 1; i <= 9; i++)            for (int j = 0; j < 4; j++)            {                if (same(i)) cor[i][j] =1;                change(i);            }        bfs(State(0,0,0,0,0,0,0,0,0));        pf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击