POJ1753 Flip Game

题目链接:http://poj.org/problem?id=1753

题目大意:

        翻棋子游戏,给定一个4*4的棋盘上摆放的初始状态,棋子有黑白两色,求将所有棋子翻成同一色的最少步数。规则:每次最多翻转一个棋子和其上下左右共五个棋子,则最少三个,因为四个角上的棋子在边界上,有两个邻居不存在。若无法翻转成同一个颜色则输出 "IImpossible",初始状态即为目标状态时输出0。

题目思路:

        棋子总共只有两种颜色,则可用0或1表示当前状态,共十六颗棋子则总共只有2^16=65536种状态。

则我们可以用一个hash判重,将当前状态一个十六位的二进制数转换成十进制数标记。解决了状态标记,判重问题,接下来就只需一个基础的BFS即可!

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 70000
int queue[MAX];
int step[MAX];  //记录走到当前状态的最少步数
int a[16];
int n,m;
void find(int x)  //将一个十进制数转换成二进制数
{
     int i=16,k=0;
     while (i--)
     {
           a[k]=x%2;
           x=x/2;
           k++;
     }
}
int check()  //将二进制数转换成十进制数
{
    int s=a[0],temp=1,i;
    for (i=1;i<16;i++)
    {
        temp*=2;
        s+=a[i]*temp;
    }
    return s;       
}
void bfs()
{
     int qe=0,qs=0,i,u; 
     queue[qe++]=n;  //初始状态入队
     step[n]=0; 
     while (qs<qe)
     {
           int temp=queue[qs++];
           if (temp==0||temp==65535)
           {
              m=step[temp];
              break;                           
           }
           find(temp);
           for (i=0;i<16;i++)  //每次最多有十六个状态可扩展
           {
               int s,x,z,y;
               s=i-4;
               x=i+4;
               z=i-1;
               y=i+1;
               a[i]=(a[i]+1)%2;
               if (s>=0&&s<16)   //判断与当前棋子相邻的上方的棋子能否翻转
                  a[s]=(a[s]+1)%2;
               if (x>=0&&x<16)
                  a[x]=(a[x]+1)%2;
               if ((y>=0&&y<16)&&i%4!=3)  //当前棋子在右边界时,与其相邻的右方的棋子不能翻转
                  a[y]=(a[y]+1)%2;
               if ((z>=0&&z<16)&&i%4!=0)  //当前棋子在左边界时,与其相邻的左方的棋子不能翻转
                  a[z]=(a[z]+1)%2;
               //printf("%d %d %d %d\n",a[s],a[x],a[z],a[y]);
               u=check();
               //printf("%d\n",u);
               if (step[u]==-1||(step[u]>step[temp]+1))  //判断当前节点是否已扩展过,并且是否是最优。
               {
                  queue[qe++]=u;
                  step[u]=step[temp]+1;
               }
	      //将翻转过的棋子复位,供下一次扩展
               a[i]=(a[i]+1)%2;
               if (s>=0&&s<16)
                  a[s]=(a[s]+1)%2;
               if (x>=0&&x<16)
                  a[x]=(a[x]+1)%2;
               if ((y>=0&&y<16)&&i%4!=3)
                  a[y]=(a[y]+1)%2;
               if (z>=0&&z<16&&i%4!=0)
                  a[z]=(a[z]+1)%2;
               //int t=check();
               //printf("\n");
               //printf("%d %d\n",u,step[u]);
           }
     }
}
int main()
{
    //while (1)
    //{
    int i,j,s=1;
    char c;
    n=0;  //记录初始状态的十进制数
    //memset(flag,0,sizeof(flag));
    memset(step,-1,sizeof(step));
    for (i=0;i<4;i++)
    {
        for (j=0;j<4;j++)
        {
            if (i!=0||j!=0)
               s*=2;
            c=getchar();
            if (c=='b')
            {
               n+=s*1;      
            }    
            else
            {
               n+=s*0; 
            }
            //printf("%d\n",n);
        }    
        getchar();
    }
    //printf("%d\n",n);
    m=-1;
    //system("pause");
    bfs();
    if (m!=-1)
       printf("%d\n",m);
    else
       printf("Impossible\n"); 
    //system("pause");
    //}
    return 0;    
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章