摘要

题目链接 难度等级 完成状态 完成分数 最后编辑时间 失误原因(初次提交分数)
四子连棋 ★☆☆☆☆ 答案正确 100 2014/12/04 19:42:46 看漏条件(45)

题意

在4*4的棋盘,黑白双方交替走棋,任意一方可以先走,求到四子连棋的最小步数。

题解

  • 很明显就数据量来说,肯定是搜索题,一般来说求最小路径肯定是广搜。
  • 出于偷懒,写了迭代加深搜索。和广搜类似,由于前面若干层的搜索数据量十分小,可以通过限制并且不断加大搜索深度,以此来实现类似广度优先搜索的层次遍历。
  • 关于遍历:用一个delta数组来处理变化,详见5、96行。
  • 判重:其实不判重也能过了(已测试,注释掉86-89行),这里判重用了3进制压位(详见getID函数)。
  • 关于爆内存:好像ACM是无所谓内存的,一般来说128MB内存大概是3kw的int,6kw的short,12kw的bool,OIers特别注意下。

代码

1004.cpp代码已折叠
展开折叠内容
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int deltaX[4]={0,0,1,-1},deltaY[4]={1,-1,0,0};
char oC[2]={'B','W'};
class state
{
    private:
        char a[5][5];
    public:
        const bool isEnd() const
        {
            for(int i=1;i<=4;++i)
            {
                int xEnd=1,yEnd=1;
                for(int j=2;j<=4;++j)
                {
                    if(a[j][i]!=a[j-1][i]||a[j][i]=='O')
                        xEnd=0;
                    if(a[i][j]!=a[i][j-1]||a[i][j]=='O')
                        yEnd=0;
                }
                if(xEnd||yEnd)
                    return 1;
            }
            int d1End=1,d2End=1;
            for(int i=2;i<=4;++i)
            {
                if(a[i][i]!=a[i-1][i-1]||a[i][i]=='O')
                    d1End=0;
                if(a[i][5-i]!=a[i-1][5-i+1]||a[i][5-i]=='O')
                    d2End=0;
            }
            if(d1End||d2End)
                return 1;
            return 0;
        }
        void init()
        {
            for(int i=1;i<=4;++i)
            {
                for(int j=1;j<=4;++j)
                    cin>>a[i][j];
            }
        }
        void p()
        {
            for(int i=1;i<=4;++i)
            {
                for(int j=1;j<=4;++j)
                    cout<<a[i][j];
            cout<<endl;
            }
        }
        inline const int getId() const
        {
            int p=0,u=1;
            for(int i=1;i<=4;++i)
                for(int j=1;j<=4;++j)
                {
                    if(a[i][j]=='B')
                        p+=1*u;
                    if(a[i][j]=='W')
                        p+=2*u;
                    u*=3;
                }
            return p;
        }
        inline char *at(const int& x,const int& y)
        {
            if(x<1||x>4||y<1||y>4)
                return NULL;
            return &a[x][y];
        }
};
int stepL;
short stepD[50000000]={}; 
const bool dfs(state now,const int &step,bool color)
{
    //now.p();
    if(step>stepL)
        return 0;
    if(now.isEnd())
        return 1;
    int nid=now.getId();
    if(stepD[nid]&&stepD[nid]<step)
        return 0;
    stepD[nid]=step;
    for(int i=1;i<=4;++i)
    {
        for(int j=1;j<=4;++j)
        {
            for(int dir=0;dir<4;++dir)
            {
                int newi=i+deltaX[dir],newj=j+deltaY[dir];
                if(now.at(newi,newj)==NULL)
                    continue;
                if(*now.at(newi,newj)!='O'||*now.at(i,j)!=oC[color])//第一次写的时候没有看到要交替下棋 
                    continue;
                swap(*now.at(newi,newj),*now.at(i,j));
                if(dfs(now,step+1,!color))
                    return 1;
                swap(*now.at(newi,newj),*now.at(i,j));  
            }
        }
    }
    return 0;
}
state c;
int main()
{
    c.init();
    for(stepL=1;stepL<=100;++stepL)
    {
        if(dfs(c,1,0)||dfs(c,1,1)){
            printf("%d",stepL-1);
            return 0;
        }
                    
    }
}

著作权声明[编辑]

关于[编辑]