• 聪明的打字员---poj1184(bfs)


    题目链接:http://poj.org/problem?id=1184

    分析:首先可以发现有6*10^6种状态,比较多,不过搜索的时候可以去除一些无用的状态,

    可以发现一个点的值(2-5)如果想要改变那么光标必须在该点处,

    所以当光标在2-5位置时候,必须要要把值变为与目标位置处一样才可以移动。

    单搜:

    #include<stdio.h>
    #include<queue>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define N 1000002
    int vis[7][N];
    int a0[10], b0[10], A, B;
    struct node
    {
        int k;///光标所在位置
        int num;
        int step;
    };
    
    void FenNum(int n, int a[])///把n的每位数字存到a数组中;
    {
        int i=6;
        while(i)
        {
            a[i--]=n%10;
            n/=10;
        }
    }
    
    node Op(int a[], int op, node p)
    {
        if(op==0)
            swap(a[p.k], a[1]);
        if(op==1)
            swap(a[p.k], a[6]);
        if(op==2 && a[p.k]!=9)
            a[p.k]++;
        if(op==3 && a[p.k]!=0)
            a[p.k]--;
        if(op==4 && p.k!=1)
            p.k--;
        if(op==5 && p.k!=6)
            p.k++;
        p.num=0;
        for(int i=1; i<=6; i++)
            p.num = p.num*10+a[i];
        return p;
    }
    int bfs(int num)
    {
        node p;
        queue<node>Q;
        p.k=1;
        p.num = num;
        p.step = 0;
        Q.push(p);
        memset(vis, 0, sizeof(vis));
        vis[p.k][p.num] = 1;
        while(Q.size())
        {
            p=Q.front();
            Q.pop();
            if(p.num==B)
                return p.step;
    
            for(int i=0; i<6; i++)
            {
                FenNum(p.num, a0);
                if((i==4||i==5) && p.k<=5 && p.k>=2 &&  a0[p.k]!=b0[p.k])
                    continue;
                node pn = Op(a0, i, p);
                if(vis[pn.k][pn.num]==0)
                {
                    pn.step=p.step+1;
                    Q.push(pn);
                    vis[pn.k][pn.num] = 1;
                }
            }
        }
        return -1;
    }
    int main()
    {
        scanf("%d%d", &A, &B);
        FenNum(B, b0);
        int ans = bfs(A);
        printf("%d
    ", ans);
    }
    View Code

    双搜:(我只看了看)

    #include<stdio.h>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    const int MAXN = 1e6;
    
    char used[MAXN][2][7];
    
    struct node
    {
        int pass[7];///保存密码
        int cursor;///光标所在位置
        int op;///op等于0表示从原始密码开始,等于1表示从目标密码开始
        int step;///步数
    };
    
    int TurnNum(node s)
    {
        int sum=0;
    
        for(int i=1; i<7; i++)
            sum = sum*10 + s.pass[i];
    
        return sum;
    }
    void TurnStr(node &s, int M)
    {
        for(int i=6; i>0; i--)
        {
            s.pass[i] = M % 10;
            M /= 10;
        }
    }
    int BFS(node s, node e)
    {
        queue<node> Q;
        Q.push(s);
        int k = TurnNum(s);
        used[k][0][1] = true;
        k = TurnNum(e);
        for(int i=1; i<7; i++)
        {
            e.cursor = i;
            used[k][1][i] = true;
            Q.push(e);
        }
    
        int p[2][7];
    
        for(int i=1; i<=6; i++)
        {///保存一下原始密码,和目标密码
            p[0][i] = s.pass[i];
            p[1][i] = e.pass[i];
        }
    
        while(Q.size())
        {
            s = Q.front();
            Q.pop();
    
            for(int i=1; i<=6; i++)
            {
                e = s;
    
                if(i == 1)
                    swap(e.pass[e.cursor], e.pass[1]);
                else if(i == 2)
                    swap(e.pass[e.cursor], e.pass[6]);
                else if(i == 3 && e.pass[e.cursor] != 9)
                    e.pass[e.cursor] += 1;
                else if(i == 4 && e.pass[e.cursor] != 0)
                    e.pass[e.cursor] -= 1;
                else if(i == 5 && ( (e.cursor>=2 && e.cursor<=5 && e.pass[e.cursor]==p[e.op^1][e.cursor]) || e.cursor==6) )
                    e.cursor -= 1;
                else if(i == 6 && ( (e.cursor>=2 && e.cursor<=5 && e.pass[e.cursor]==p[e.op^1][e.cursor]) || e.cursor==1) )
                    e.cursor += 1;
    
                k = TurnNum(e);
    
                if(used[k][e.op][e.cursor] == 0)
                {
                    if(used[k][e.op^1][e.cursor])
                    {
                        return used[k][e.op^1][e.cursor] + e.step-1;
                    }
    
                    e.step += 1;
                    used[k][e.op][e.cursor] = e.step;
                    Q.push(e);
                }
            }
        }
    
        return -1;
    }
    
    int main()
    {
        int S, E;
        node s, e;
    
        scanf("%d%d", &S, &E);
    
    
        if(S == E)
        {
            printf("%d
    ", 0);
            return 0;
        }
    
        TurnStr(s, S);
        TurnStr(e, E);
        s.cursor = 1, s.op = 0, s.step = 1;
        e.op = 1, e.step = 1;
    
        int ans = BFS(s, e);
    
        printf("%d
    ", ans);
    
        return 0;
    }
    View Code
  • 相关阅读:
    剑指Offer
    剑指Offer
    剑指Offer
    面积(area)
    最少步数
    细胞
    集合的前N个元素
    1~100卡特兰数(存一下hhhh)
    [Codeforces137C]History(排序,水题)
    [Codeforces676B]Pyramid of Glasses(递推,DP)
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4741476.html
Copyright © 2020-2023  润新知