天天看点

poj1753Flip Game

背景:说实话,看到这道题的时候一点也不会,然后朋友说了用dfs做,虽然曾经学长讲过dfs,但我没有认真听,所以还是一点也没懂,然后百度了dfs,还是晕晕的,最后实在没办法,就看了朋友的代码,这下才弄懂了什么是dfs,我下面的代码就是看了朋友的代码后,凭借记忆,用他的思路写出来的。

思路:对于每个格子,他要么被反转0次,要么1次,由于只有16个格子,所以他的总的情况有

poj1753Flip Game

所以采用dfs深度搜索,在时间上是不成问题的。

学习:dfs算法:深度优先搜索所遵循的搜索策略是尽可能“深”地搜索图。在深度优先搜索中,对于最新发现的顶点,如果它还有以此为起点而未探测到的边,就沿此边继续汉下去。当结点v的所有边都己被探寻过,搜索将回溯到发现结点v有那条边的始结点。这一过程一直进行到已发现从源结点可达的所有结点为止。如果还存在未被发现的结点,则选择其中一个作为源结点并重复以上过程,整个进程反复进行直到所有结点都被发现为止。

#include <stdio.h>
int q[5][5],ok=0;
int iswin(void)
{
    int k=q[0][0];
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            if(k!=q[i][j]) return 0;
    return 1;
}
void change(int i,int j)
{
    q[i][j]=!q[i][j];
    if(i-1>=0)   q[i-1][j]=!q[i-1][j];
    if(j-1>=0)   q[i][j-1]=!q[i][j-1];
    if(i+1<=3)   q[i+1][j]=!q[i+1][j];
    if(j+1<=3)   q[i][j+1]=!q[i][j+1];
}
void dfs(int m,int sum,int a,int b)
{
    if(ok) return;
    if(m==sum)
    {
        if(iswin()) {ok=1;printf("%d\n",sum);}
        else return;
    }
    else
    {
        for(int i=a;i<4;i++)
        {
            for(int j=b;j<4;j++)
            {
                change(i,j);
                if(j<3)  dfs(m+1,sum,i,j+1);
                if(j==3) dfs(m+1,sum,i+1,0);
                change(i,j);
            }
        }
        return;
    }
}
int main(void)
{
    char ch;
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
        {
            scanf("%c",&ch);
            if(j==3) getchar();
            q[i][j]=(ch=='b')?1:0;
        }
    if(iswin()) {printf("%d\n",0);return 0;}
    for(int k=1;k<=16;k++)
        dfs(0,k,0,0);
    if(!ok) printf("Impossible\n");
    return 0;
}