POJ 1753

题目连接:点击打开链接

解题思路:枚举所有状态,每个棋子有翻或不翻,因为要求最少翻动次数,所以每个棋子翻动奇数次等价于翻动1次,翻动偶数次等价于不翻,一共有2^16个状态,我用的是DFS,每次判断是否超出枚举范围,超出则枚举范围扩大一次,否则判断是否达到目标(定义一个函数扫描棋盘上是否有子不等于(1,1)位置的子,有则返回false,否则返回true)达到目标则搜索结束,否则搜索下一粒子的位置,直至达到本次枚举范围,网上大牛有用16进制表示棋盘状态来做的,代码也一并附上。
#include<iostream>  
using namespace std;  
char chess[6][6]={'*'};  
bool Chess[6][6]={0};  
bool finish()//判断是否全黑或全白  
{  
    int i,j;  
    for(i=1;i<=4;i++)  
        for(j=1;j<=4;j++)  
            if(Chess[i][j]!=Chess[1][1])  
                return false;  
    return true;  
}  
void flip(int m,int n)//翻棋操作  
{  
    Chess[m][n]=!Chess[m][n];  
    Chess[m-1][n]=!Chess[m-1][n];  
    Chess[m+1][n]=!Chess[m+1][n];  
    Chess[m][n+1]=!Chess[m][n+1];  
    Chess[m][n-1]=!Chess[m][n-1];  
}  
bool dfs(int x,int y,int now,int deep)  
{  
    if(now>deep)   return false;//判断是否超出枚举范围  
    if(finish())   return true;  
    for(int i=x;i<=4;i++)  
        for(int j=y;j<=4;j++)  
        {  
            flip(i,j);//翻棋  
            if(j<4)//同一行的没翻完继续翻,翻完就翻下一行  
            {if(dfs(i,j+1,now+1,deep))  return true;}//同一行  
            else  
            {if(dfs(i+1,1,now+1,deep))  return true;}//下一行  
            flip(i,j);//不成功则翻回最后一粒子重新搜索下一个目标位  
            if(j==4)//如果一列翻完且搜索失败,下一轮翻棋重新由下一行第一列开始  
                y=1;  
        }  
    return false;  
}  
int main()  
{  
    int i,j,step;  
    bool flag=false;  
    for(i=1;i<=4;i++)  
        for(j=1;j<=4;j++)  
            {  
                cin>>chess[i][j];  
                if(chess[i][j]=='b')  
                    Chess[i][j]=1;  
            }  
    for(step=0;step<=16;step++)//状态总共2^16种,即翻棋有翻0,1,2.....16粒子,共17种选择  
        if(dfs(1,1,0,step))  
        {  
            flag=true;  
            break;  
        }  
        if(flag)  
            cout<<step<<endl;  
        else  
            cout<<"Impossible\n";  
    return 0;  
}  


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值