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

题目

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;
}


你可能感兴趣的:([ZOJ 3814 Sawtooth Puzzle] bfs+状态压缩)