• 飞行员兄弟(暴力枚举)


    飞行员兄弟(暴力枚举)

    题目描述:“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有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
     著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

     

  • 相关阅读:
    实验二
    个人简介及对未来的想法
    读《构建之法》心得体会
    作业2
    个人简介
    第六次作业
    第二次作业
    个人简历
    购物系统测试缺陷报告
    读《构建之法》心得体会
  • 原文地址:https://www.cnblogs.com/yuanshixiao/p/14469649.html
Copyright © 2020-2023  润新知