飞行员兄弟(二进制暴力)

在这里插入图片描述
思路:纵观全局,把手的数量固定为16,因此利用暴力解决即可,二进制思想0代表不操作把手1代表操作把手,枚举所有状态即可,此外我们将二维数组可以映射成具体数字(映射数字/4代表横轴,映射数字%4代表列轴),具体可以参照代码注释

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char st[20][20];//存储把手初始态
char lit[20][20];//把手备份
int ans;
void turn(int t)//改变把手的行和列
{
    int dx=t/4;
    int dy=t%4;
    for(int i=0;i<=3;i++)
    {
        if(lit[i][dy]=='+')
        {
            lit[i][dy]='-';
        }
        else
        {
            lit[i][dy]='+';
        }
    }
    for(int i=0;i<=3;i++)
    {
        if(lit[dx][i]=='+')
        {
            lit[dx][i]='-';
        }
        else
        {
            lit[dx][i]='+';
        }
    }
    if(lit[dx][dy]=='+')
    {
        lit[dx][dy]='-';
    }
    else
    {
        lit[dx][dy]='+';
    }
    ans++;
}
bool check()//检查把手是否全为打开状态
{
    for(int i=0;i<=3;i++)
    {
        for(int j=0;j<=3;j++)
        {
            if(lit[i][j]=='+')
            {
                return false;
            }
        }
    }
    return true;
}
int main()
{
    int fills;
   for(int i=0;i<4;i++)
   {
       cin>>st[i];
   }
   int mins=100;
   for(int i=0;i< 1<<16;i++)//从0到2的16次方枚举
   {
       ans=0;
       memcpy(lit,st,sizeof st);
       for(int j=0;j<16;j++)
       {
          if(i>>j&1)//如果第j个把手为1则反转
          {
            turn(j);
          }
       }
       if(check()){
        mins=min(mins,ans);
        fills=i;
       }
   }
   cout<<mins<<endl;
   for(int i=0;i<=15;i++)
   {
       if(fills>>i&1)
       {
           cout<<i/4+1<<" "<<i%4+1<<endl;
       }
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44460602/article/details/107496065
今日推荐