zoukankan      html  css  js  c++  java
  • HihoCoder1654: XY游戏([Offer收割]编程练习赛39)(好久没写搜索)(已经超级简短了)

    描述

    如下图所示,在4x4的棋盘上有X和Y两种棋子各若干枚;O表示空格。

    OXXY

    YOOX

    XOOY

    XOXX

    小Hi每次可以选择任意一枚棋子,将它移动到上下左右相邻的空格中。  

    小Hi想知道最少移动多少次可以达到胜利局面:有4个X或者4个Y连成一行、一列或者对角线(两条对角线都算胜利)。

    输入

    4x4的棋盘

    输出

    达成胜利最少需要的步数。如果小Hi无论如何也达不到胜利局面,输出-1。

    样例输入

    OXXY  
    YOOX  
    XOOY  
    XOXX

    样例输出

    思路:

    数据小,达到目标的最小步骤问题,多半是搜索。但是X,Y两个形态,那么状态压缩的话,假设0是O,1是X,2是Y,则有3^16=43046721,无法二进制处理,直接用map记录string。

     数组记录关系,好简短啊。。。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<map>
    #include<queue>
    using namespace std;
    map<string,int>mp;
    queue<string>q;
    int head,tail;
    int a[5][5]={ {0}, {0,1,2,3}, {0,4,8,12},{0},       {3}           };
    int b[5][5]={ {0}, {4,8,12},  {1,2,3},   {5,10,15}, {3,6,9}       };
    int c[5][5]={ {0}, {3,7,11,15},{0,4,8,12},{12,13,14,15},{0,1,2,3} };
    int d[5]={0,1,-1,4,-4};
    using namespace std;
    bool check(string s)
    {
         for(int i=1;i<=2;i++)//1是列,2是行 ,a代表起始,b代表跨度。 
           for(int j=0;j<4;j++)//每行或者每列共4个 
             if(s[a[i][j]]!='O'&&s[a[i][j]]==s[a[i][j]+b[i][0]]&&s[a[i][j]]==s[a[i][j]+b[i][1]]&&s[a[i][j]]==s[a[i][j]+b[i][2]]) return true;
         for(int i=3;i<=4;i++)//对角线 
             if(s[a[i][0]]!='O'&&s[a[i][0]]==s[a[i][0]+b[i][0]]&&s[a[i][0]]==s[a[i][0]+b[i][1]]&&s[a[i][0]]==s[a[i][0]+b[i][2]]) return true;
         return false; 
    }
    int bfs()
    {
        string s,tmp;
        while(!q.empty()){
            s=q.front();q.pop();
            if(check(s)) return mp[s]-1;
            for(int pos=0;pos<16;pos++)
              for(int j=1;j<=4;j++){
                string tmp=s;
                if(pos==c[j][0]||pos==c[j][1]||pos==c[j][2]||pos==c[j][3]) continue;
                if(s[pos+d[j]]=='O'&&s[pos]!='O') {
                    tmp=s;tmp[pos]=s[pos+d[j]];tmp[pos+d[j]]=s[pos]; 
                    if(!mp[tmp]) q.push(tmp),mp[tmp]=mp[s]+1;
                }
            }
        } return -1;
    }
    int main()
    {
        char c[10]; string s="";
        for(int i=1;i<=4;i++){
            scanf("%s",c+1);
            s=s+c[1]+c[2]+c[3]+c[4];
        }
        q.push(s);mp[s]=1;
        printf("%d
    ",bfs());
        return 0;
    }
  • 相关阅读:
    k近邻 KNN
    聚类之k-means
    支持向量机SVM、优化问题、核函数
    [THUSC 2016] 补退选 (Trie树)
    [CQOI2016] 手机号码 (数位dp)
    [CQOI2012] 交换棋子 (费用流)
    [SCOI2016] 背单词 (Trie树)
    [JSOI2009] 球队收益 (费用流)
    [BZOJ1878][SDOI2009] HH的项链 (树状数组)
    [BZOJ2151]种树
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8119909.html
Copyright © 2011-2022 走看看