zoukankan      html  css  js  c++  java
  • P1379 八数码难题

    luogu 传送门

    bfs,像输入一样我们用一个数来表示状态,因为不能开一个9位的数组,又因为如果数的八位确定,那么最后一位就能确定,所以我们可以开一个8位的数组来记录这个状态是否进过队。

    重点是将0与其它位转换,基于九宫格的特点,我们只能将0与和它相距 1 -1 3 -3 位的数字交换,下面是数位交换的原则:
    1. 要得到第x位前面的部分:/10^x
    2. 要得到第x位后面的部分:%10^(x-1)
    3. 要得到第x位的部分:/10^(x-1) %10

    还需要注意一个问题(一开始自己忽略掉了),就是0在九宫格的最右边是不能与下一位的数交换,同理在最左边时,也不能与上一位的数字交换。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define T 123804765
    using namespace std;
    int ans,s;
    bool f[88888888];
    int MOD[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};//MOD[i]是10^i 
    struct H{
        int x,step;
    };
    int mov[]={-1,1,-3,3};//0的移动方向:左右上下 
    int bfs()
    {
        queue <H> q;
        H k;
        k.x=s;k.step=0;
        f[s/10]=1;
        q.push(k);
        while(!q.empty())
        {
            k=q.front();
            q.pop();
            if(k.x==T) return k.step;
            int j=1,p=k.x;
            while(p%10)
            {j++;p/=10;}//第几位是0 
            for(int i=0;i<4;i++)
            {
                int t=j,tt=j+mov[i];//0要交换到的位
    
                if(t%3==0&&mov[i]==1) continue;
                if(t%3==1&&mov[i]==-1) continue;
    
                if(tt>=1&&tt<=9)
                {
                    if(t<tt) swap(t,tt);
                    int x;
                    x=k.x/MOD[t]*MOD[t]+k.x%MOD[tt-1];
                    int x1=k.x/MOD[t-1]%10;
                    int x2=k.x/MOD[tt-1]%10;
                    int x3=((k.x/MOD[tt]*MOD[tt])%MOD[t-1]);
                    x+=x3+x1*MOD[tt-1]+x2*MOD[t-1];
                    if(!f[x/10])
                    {
                        H l;
                        if(x==T) return k.step+1;
                        l.x=x,l.step=k.step+1;
                        q.push(l);f[x/10]=1;
                    }
                }
            }
    
        }
    }
    int main()
    {
        scanf("%d",&s);
        ans=bfs();
        printf("%d",ans);
        return 0;
    } 
  • 相关阅读:
    [转][黄忠成]Object Builder Application Block
    C#中的接口
    委托、事件与Observer设计模式
    [转][黄忠成]Object Builder Application Block (1)
    C# 中的委托和事件
    Android布局充分演示Demo
    android代码重启 .
    【转】小游戏>弹球
    多个Icon的APk——实现多程序入口总结
    为你的Android应用定制属于你的BaseActivity
  • 原文地址:https://www.cnblogs.com/dfsac/p/7587857.html
Copyright © 2011-2022 走看看