翻牌Flip Game POJ 1753

http://poj.org/problem?id=1753

这个题目一看就要用搜索,但是如何最小?  题目只有4*4 行 ,所以好说了,暴力dfs。

 1 #include<stdio.h>
 2 char map[4][4];
 3 int vis[4][4];
 4 int step,flag;
 5 int judge()
 6 {
 7      int i,j;
 8      for(i=0;i<4;i++)
 9        for(j=0;j<4;j++)
10          if(vis[i][j]!=vis[0][0])
11          return 0;
12 
13          return 1;
14 }
15 void turn(int i,int j)
16 {
17      vis[i][j]=!vis[i][j];
18      if(i>0) vis[i-1][j]=!vis[i-1][j];
19      if(i<3)  vis[i+1][j]=!vis[i+1][j];
20      if(j>0)  vis[i][j-1]=!vis[i][j-1];
21      if(j<3)  vis[i][j+1]=!vis[i][j+1];
22 }
23 void dfs(int i,int j,int step1)
24 {
25 
26      if(step==step1)
27      {
28           if(judge())
29           flag=1;
30 
31           return ;
32      }
33      if(flag ||i==4)  return ;
34      turn(i,j);
35      if(j<3)
36      dfs(i,j+1,step1+1);
37      else
38      dfs(i+1,0,step1+1);
39      turn(i,j);
40           if(j<3)
41      dfs(i,j+1,step1);
42      else
43      dfs(i+1,0,step1);
44      return ;
45 }
46 int main()
47 {
48      int i,j;
49      for(i=0;i<4;i++)
50      scanf("%s",map[i]);
51      for(i=0;i<4;i++)
52      {
53           for(j=0;j<4;j++)
54           {
55                if(map[i][j]=='b')
56           vis[i][j]=1;
57           else
58           vis[i][j]=0;
59 
60           }
61 
62      }
63      flag=0;
64      for(step=0;step<=16;step++)
65      {
66           dfs(0,0,0);
67           if(flag)
68           break;
69      }
70      if(flag)
71      printf("%d
",step);
72      else
73      printf("Impossible
");
74      return 0;
75 }
View Code

基于以上代码,我自己又写了一个,本想优化优化,结果一直wa,看了一下午加一晚上,还是没有搞清。

找啊找,找不同。先把代码放在这里,过几天再看看,说不定就找到原因了,读者能找到不同么?欢迎来踩!

 1 #include<stdio.h>
 2 #include<string.h>
 3 char m[4][10];
 4 int s[4][4];
 5 int limit;
 6 int ok=0;//是否完成反转,为一时,全部一样
 7 int check()
 8 {
 9     for(int i=0;i<4;i++)
10         for(int k=0;k<4;k++)
11     {
12         if(s[i][k]!=s[0][0])return 0;
13     }
14     return 1;//全部一样的时候返回1,不一样的时候返回0
15 }
16 void turn(int x,int y)
17 {
18     s[x][y]=!s[x][y];
19     if(x>=1)s[x-1][y]=!s[x-1][y];
20     if(x<=2)s[x+1][y]=!s[x+1][y];
21     if(y>=1)s[x][y-1]=!s[x][y-1];
22     if(y<=2)s[x][y+1]=!s[x][y+1];
23 }
24 void dfs(int x,int y,int step)
25 {   
26     if(step==limit&&check()){ok=1;printf("%d
",limit);return;}
27     if(x<0||y<0||x>=4||y>=4||step>limit||ok)
28     {
29         return;
30     }
31 
32     turn(x,y);//假设要翻开
33     if(y<=2)dfs(x,y+1,step+1);
34     else dfs(x+1,0,step+1);
35     turn(x,y);//运行到此步说明以上翻牌不行时,应该翻回去,翻其他的牌
36     if(y<=2)dfs(x,y+1,step);
37     else dfs(x+1,0,step);
38     return ;
39 }
40 
41 int main()
42 {
43     for(int i=0;i<4;i++)
44         scanf("%s",m[i]);
45     for(int i=0;i<4;i++)
46         {
47             //printf("%s
",m[i]);
48             for(int k=0;k<4;k++)
49             {
50                 if(m[i][k]=='b')s[i][k]=0;
51                 else s[i][k]=1;
52             }
53         }
54 
55     for(limit=0;limit<=16;limit++)
56     {
57         dfs(0,0,0);
58         if(ok==1)break;
59     }
60     if(ok==0)printf("Impossible
");
61     else printf("%d
",limit);
62     return 0;
63 }
View Code

 无语了,原来我在函数验证时输出了一次,忘记把代码注释掉。

一段时间后,我又重写了此题,作为复习,发现新的代码更为清晰。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define M 4
#define mem0(f) memset(f,0m,sizeof(f))
char s[10][10];
int map[M][M];
int ok,limit;
void check()
{
    for(int i=0;i<M;i++)
        for(int k=0;k<M;k++)
    {
        if(map[i][k]!=map[0][0])
        {
            ok=0;return;
        }
    }
    ok=1;
}
void turn(int x,int y)
{
    map[x][y]=!map[x][y];
    if(x>0)map[x-1][y]=!map[x-1][y];
    if(x<M-1)map[x+1][y]=!map[x+1][y];
    if(y>0)map[x][y-1]=!map[x][y-1];
    if(y<M-1)map[x][y+1]=!map[x][y+1];
}
void dfs(int x,int y,int step)
{
    check();
    //printf("ok=%d
",ok);
    if(x<0||y<0||x>=M||y>=M||ok==1||step==limit)return;
    turn(x,y);
    if(x==M-1)dfs(0,y+1,step+1);
    else dfs(x+1,y,step+1);
    if(ok)return;
    turn(x,y);
    if(x==M-1)dfs(0,y+1,step);
    else dfs(x+1,y,step);
    return;
}
int main()
{
    while(~scanf("%s",s[0]))
    {
        scanf("%s",s[1]);
        scanf("%s",s[2]);
        scanf("%s",s[3]);
        for(int i=0;i<M;i++)
        {
            for(int k=0;k<M;k++)
            {
                if(s[i][k]=='b')map[i][k]=0;
                else map[i][k]=1;
            }
        }
        ok=0;
        for(int i=0;i<=16;i++)
        {
            limit=i;
            dfs(0,0,0);
            if(ok){break;}
        }
        if(ok)printf("%d
",limit);
        else printf("Impossible
");
    }
    return 0;
}
View Code

这应该也是思维提升的表现吧。好了,好好加油,看看日后有没有一个比这个暴力的方法更好的解法,毕竟搜索时这个算法重复了好多次。

原文地址:https://www.cnblogs.com/plank-george-zzo/p/3207946.html