飞行员兄弟(暴力枚举)

飞行员兄弟(暴力枚举)

题目描述:“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。已知每个把手可以处于以下两种状态之一:打开或关闭。

只有当所有把手都打开时,冰箱才会打开。

把手可以表示为一个4х4的矩阵,您可以改变任何一个位置[i,j]上把手的状态。

但是,这也会使得第i行和第j列上的所有把手的状态也随着改变。

请你求出打开冰箱所需的切换把手的次数最小值是多少。

输入格式

输入一共包含四行,每行包含四个把手的初始状态。

符号“+”表示把手处于闭合状态,而符号“-”表示把手处于打开状态。

至少一个手柄的初始状态是关闭的。

输出格式

第一行输出一个整数N,表示所需的最小切换把手次数。

接下来N行描述切换顺序,每行输入两个整数,代表被切换状态的把手的行号和列号,数字之间用空格隔开。

注意:如果存在多种打开冰箱的方式,则按照优先级整体从上到下,同行从左到右打开。

数据范围

1≤i,j≤4

输入样例:

 -+--
 ----
 ----
 -+--

输出样例:

 6
 1 1
 1 3
 1 4
 4 1
 4 3
 4 4

 

 #include<algorithm>
 #include<iostream>
 #include<cstring>
 #include<cstdio>
 using namespace std;
 
 char g[6][6];//把手矩阵,将来我们都是对这个数组做处理
 char backup1[6][6];//备份作用,每循环一次,就将backup1中的数据拷回g中。
 int way[6][6];//way数组保存的是哪个把手要进行状态转换,如:way[1][1]=1,就表示2 2这个把手需要被转换
 int backup2[6][6];//backup2用来保存最终结果。只要发现step比res小,就将way中的数据拷入到backup2中,更新最优解。
 
 void turn(int x,int y){
 
     for(int i=0;i<4;i++){
         if(g[x][i]=='-'){
             g[x][i]='+';
        }else{
             g[x][i]='-';
        }
    }
     for(int j=0;j<4;j++){
         if(g[j][y]=='-'){
             g[j][y]='+';
        }else{
             g[j][y]='-';
        }
    }
 
     //turn方法比较简单,但是x,y这个点需要注意,该点要被转换三次(两次for回到最初,所以还需额外一次),
     //所以下面这几行代码不能少。我就是在这栽了15分钟。。。。。。
     if(g[x][y]=='-'){
         g[x][y]='+';
    }else{
         g[x][y]='-';
    }
 }
 
 int main(){
     for(int i=0;i<4;i++) cin>>g[i];//读入把手矩阵
     long long res = 9999999999;//起初把res设的尽可能大
     for(long long i=0;i<1<<16;i++){//因为i范围很小,所以我们就算一一枚举1<<16的把手状态也不会超时
         int step=0;
         memcpy(backup1,g,sizeof g);
 
         memset(way,0,sizeof way);//每次循环都要将way数组置零
 
 
         for(int j=0;j<16;j++){
             if(i>>j&1){//表示低位把手要转换状态
                 step++;
                 turn(j/4,j%4);
                 way[j/4][j%4]=1;
            }
        }
         //内层循环完成后,判断把手是否全部开启
         bool success = true;
         for(int i=0;i<16;i++){
             if(g[i/4][i%4]=='+'){
                 success = false;
                 break;
            }
        }
 
         if(success) {
             if(res>step){
                 memcpy(backup2,way,sizeof way);
                 res = step;
            }
        }
 
 
         memcpy(g,backup1,sizeof g);//循环结束,把备份把手矩阵拷回g。
    }
 
     cout<<res<<endl;
     //bool win = true;
     for(int i=0;i<16;i++){
         if(backup2[i/4][i%4]){
             cout<<(i/4)+1<<" "<<(i%4)+1<<endl;
        }
    }
 
     return 0;
 }
 
 作者:rookie_14
 链接:https://www.acwing.com/activity/content/code/content/931103/
 来源:AcWing
 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

原文地址:https://www.cnblogs.com/yuanshixiao/p/14469649.html