• 洛谷 题解 P1225 【黑白棋游戏】


    看见很多dalao写了什么双向BFS,蒟蒻表示不会写啊。

    怎么办办?

    先来分析一下题目,一眼看去就是一个搜索题,考虑DFS与BFS。

    先放一份DFS的代码:

    #include<bits/stdc++.h>
    using namespace std;
    bool a[5][5],b[5][5];
    char c;
    int dx[5]={0,0,0,1,-1};
    int dy[5]={0,1,-1,0,0};
    int ans=0x3f3f3f3f;
    int ax[110],bx[110],ay[110],by[110];
    int ansx1[110],ansx2[110],ansy1[110],ansy2[110];
    int cnt=0,ans_cnt;
    map<string,int>mp;
    inline string get()
    {
        string s="";
        for(int i=1;i<=4;i++)
            for(int j=1;j<=4;j++)s+=a[i][j]+'0';
        return s;
    }
    inline bool check()
    {
        for(int i=1;i<=4;i++)
            for(int j=1;j<=4;j++)
                if(a[i][j]!=b[i][j])return 0;
        return 1;
    }
    inline void DFS(int x,int y,int tot)
    {
        /*for(int i=1;i<=4;i++)
        {
            for(int j=1;j<=4;j++)cout<<a[i][j];
            cout<<endl;
        }
        cout<<tot<<endl;*/
        //Sleep(100);
        if(tot>=ans)return;
        if(check())
        {
            ans=tot;
            ans_cnt=cnt;
            for(int i=1;i<=cnt;i++)
            {
                ansx1[i]=ax[i];
                ansx2[i]=bx[i];
                ansy1[i]=ay[i];
                ansy2[i]=by[i];
            }
        }
        if(y==5)return;
        if(x==5)x=1,y++;
        /*string s=get();
        cout<<s<<endl;
        if(mp[s]<tot&&mp[s]!=0)return;
        mp[s]=tot;*/
        DFS(x+1,y,tot);
        for(int i=1;i<=4;i++)
        {
            int aa=dx[i]+x,bb=dy[i]+y;
            if(aa<1||aa>4||bb<1||bb>4||a[aa][bb]==a[x][y])continue;
            cnt++;
            ax[cnt]=x;ay[cnt]=y;
            bx[cnt]=aa;by[cnt]=bb;
            swap(a[aa][bb],a[x][y]);
            DFS(x+1,y,tot+1);
            cnt--;
            swap(a[aa][bb],a[x][y]);
        }
    }
    int main()
    {
        for(int i=1;i<=4;i++)
            for(int j=1;j<=4;j++)
            {
                cin>>c;
                if(c=='1')a[i][j]=1;
                else a[i][j]=0;
            }
        for(int i=1;i<=4;i++)
            for(int j=1;j<=4;j++)
            {
                cin>>c;
                if(c=='1')b[i][j]=1;
                else b[i][j]=0;
            }
        DFS(1,1,0);
        cout<<ans<<endl;
        for(int i=1;i<=ans_cnt;i++)
        {
            cout<<ansx1[i]<<ansy1[i]<<ansx2[i]<<ansy2[i]<<endl;
        }
        return 0;
    }
    

    这里枚举每一个点,进行上下左右的交换。看上去很(fei)有(chang)道(che)理(dan)的样子,但是很明显,有时候交换完下面的点还可以去交换上面的点,所以有时候会搜不到答案,只能拿到60分

    蓝题能拿60分也很不错了呢

    怎么办办?

    那么当然要用BFS啦,(蒟蒻不会记录方案的好办法,只能暴力存储啦)

    #include<bits/stdc++.h>
    using namespace std;
    bool a[5][5],b[5][5];
    char c;
    int dx[5]={0,0,0,1,-1};
    int dy[5]={0,1,-1,0,0};//上下左右
    int ans=0x3f3f3f3f;
    int ansx1[100],ansx2[100],ansy1[100],ansy2[100];
    map<string,int>mp;//剪枝专用
    struct Node
    {
        bool cc[5][5];//记录当前局势
        int tot;//记录总数
        int x1[20],x2[20],y1[20],y2[20];//记录方案
    };
    inline void BFS()
    {
        queue<Node>q;
        Node now;
        now.tot=0;
        for(int i=1;i<=4;i++)
            for(int j=1;j<=4;j++)
                now.cc[i][j]=a[i][j];//把局势copy一份
        q.push(now);
        while(q.size())
        {
            Node now=q.front();
            /*for(int i=1;i<=4;i++)
            {
                for(int j=1;j<=4;j++)cout<<now.cc[i][j];
                cout<<endl;
            }
            cout<<now.tot<<endl;*/
            q.pop();
            bool flag=1;
            for(int i=1;i<=4;i++)
                for(int j=1;j<=4;j++)if(now.cc[i][j]!=b[i][j])flag=0;
            if(flag)//找到答案
            {
                ans=now.tot;//更新答案
                for(int i=1;i<=ans;i++)
                {
                    ansx1[i]=now.x1[i];
                    ansx2[i]=now.x2[i];
                    ansy1[i]=now.y1[i];
                    ansy2[i]=now.y2[i];
                }//更新方案
                return;
            }
            string s="";
            for(int i=1;i<=4;i++)
                for(int j=1;j<=4;j++)s+=now.cc[i]
            //cout<<q.size()<<" "<<s<<" "<<mp[s]<<endl;
            if(mp[s]!=0&&mp[s]<=now.tot)continue;[j]+'0';//当前状态如果已经有更优解了,那就不用搜了(状态压缩的思想)
            mp[s]=now.tot;
            Node next;
            next.tot=now.tot+1;
            for(int i=1;i<=4;i++)
                for(int j=1;j<=4;j++)next.cc[i][j]=now.cc[i][j];//把方案copy一份(由于蒟蒻想不到好方法,还请dalao勿喷)
            for(int i=1;i<=now.tot;i++)
            {
                next.x1[i]=now.x1[i];next.y1[i]=now.y1[i];
                next.x2[i]=now.x2[i];next.y2[i]=now.y2[i];
            }
            for(int i=1;i<=4;i++)
            {
                for(int j=1;j<=4;j++)
                {
                    for(int k=1;k<=4;k++)
                    {
                        int aa=dx[k]+i;
                        int bb=dy[k]+j;
                        if(aa<1||bb<1||aa>4||bb>4||now.cc[i][j]==now.cc[aa][bb])continue;//超过边界或为相同数字,那么就continue
                        swap(next.cc[aa][bb],next.cc[i][j]);//交换
                        next.x1[next.tot]=i;next.y1[next.tot]=j;
                        next.x2[next.tot]=aa;next.y2[next.tot]=bb;//添加新方案
                        q.push(next);
                        swap(next.cc[aa][bb],next.cc[i][j]);//回溯
                    }
                }
            }
        }
    }
    int main()
    {
        for(int i=1;i<=4;i++)
            for(int j=1;j<=4;j++)
            {
                cin>>c;
                if(c=='1')a[i][j]=1;
                else a[i][j]=0;
            }
        for(int i=1;i<=4;i++)
            for(int j=1;j<=4;j++)
            {
                cin>>c;
                if(c=='1')b[i][j]=1;
                else b[i][j]=0;
            }
        BFS();
        cout<<ans<<endl;
        for(int i=1;i<=ans;i++)
        {
        	cout<<ansx1[i]<<ansy1[i]<<ansx2[i]<<ansy2[i]<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    javascript函数apply和call
    【剑指offer】面试题42. 连续子数组的最大和
    【SQL】排名
    【剑指offer】面试题21. 调整数组顺序使奇数位于偶数前面
    【剑指offer】 面试题29. 顺时针打印矩阵
    【剑指offer】面试题58
    【剑指offer】面试题34. 二叉树中和为某一值的路径
    【SQL】取第n个
    【剑指offer】面试题55
    【剑指offer】面试题55
  • 原文地址:https://www.cnblogs.com/hulean/p/11056741.html
Copyright © 2020-2023  润新知