zoukankan      html  css  js  c++  java
  • # 费解的开关(二进制+递推+思维)

    费解的开关(二进制+递推+思维)


    • 题意:5*5的灯阵,每次按一盏灯的开关,并且这盏灯的上下左右也受到相同的影响(0->1,1->0),求使给定灯阵全1的最少步数。

    • 题解:

      • 每盏灯最多点击一次,点击两次相当于没有点击。
      • 最重要的性质:如果我们确定了第1行的灯的情况的话,那么后面的行数都可以依此递推,当前行灭的灯只能由下一行同一列的灯使之点亮。
    • 附上一个写的较好的题解

    举个例子
    11011
    10110
    01111
    11111
    第一行中第三盏灯为0,那么必须通过第二行的第3张灯将其点亮,当前行的灯只能由下一行的灯点亮,这样才不会影响当前行其他灯的情况。所以只需要确定第一行的灯的情况即可,第一行的灯控制第二行灯的点击情况,通过第二行灯将第一行灭的灯点亮后, 第二行灯处于灭状态的灯由第三行点亮,依次类推
    
    • Code:
    //模块化编程思想
    
    #include <bits/stdc++.h>
    using namespace std;
    
    #define mem(a) memset((a),0,sizeof(a))
    #define fo(i,a,b) for(int (i)=(a);(i)<(b);(i)++)
    #define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)//宏定义,编译时展开,占用编译时间
    #define sf(x) scanf("%d",&(x))
    const int inf=(0x7f7f7f7f);
    const int maxn=3000;
    
    int n;
    int mp[5][5];
    int dx[]={0,-1,0,1,0};
    int dy[]={0,0,1,0,-1};
    
    void turn(int x,int y){
        fo(i,0,5){
            int xx=x+dx[i];
            int yy=y+dy[i];
            if(xx>=0&&xx<5&&yy>=0&&yy<5){
                mp[xx][yy]^=1;
            }
        }
    }
    
    char mmp[5][5];
    int work(){
        int ans=(1<<30);
        int cnt=0;
    
    
    	//fo(i)循环枚举第一行灯的所有可能的点击情况,10010(表示点击第一盏灯和第四盏灯) 
        fo(i,0,31){
        	//初始化, 
            fo(x,0,5)fo(y,0,5)mp[x][y]=mmp[x][y]-'0';
            cnt=0;
    		
    		//通过二进制数解码出灯的点击情况 
            fo(j,0,5)
                if((i>>j)&1){
                    cnt++;
                    turn(0,j);
                }
    
    		//依次处理前4行灯 
            fo(j,0,4){
                fo(k,0,5){
                    if(mp[j][k]==0){
                        turn(j+1,k);//通过下一行的灯使其点亮 
                        cnt++;
                    }
                }
            }
    
    		//检查第五行灯是否是全亮的情况,如果不是由于前4行是全1的情况
    		//第五行灭的灯无法点亮,故当前方案不合理 
            bool is_ok=1;
            fo(j,0,5)if(mp[4][j]==0){
                is_ok=0;
                break;
            }
            
            if(is_ok)
            ans=min(ans,cnt);
    
        }
    
        if(ans>6)return -1;
        return ans;
    }
    
    int main(){
        sf(n);
        while(n--){
            fo(i,0,5)scanf("%s",mmp[i]);
    
            //fo(i,0,5)fo(j,0,5)cout<<mmp[i][j];
    
    
            cout<<work()<<endl;
        }
    
        return 0;
    }
    
  • 相关阅读:
    9个数中取最大值最小值速度问题
    ubuntu 12.04安装git 1.8.11
    <转>Win7资源管理器更新后不断重启解决方案
    windows下安装安卓开发环境和NDK支持
    饱和算法
    bzip21.0.6
    《转》GetFileTitle与文件扩展名是否显示有关
    Ubuntu设置环境变量PATH的三种方法 <转>
    ubuntu下使用脚本交叉编译windows下使用的ffmpeg
    UnxUtils windows下linux命令
  • 原文地址:https://www.cnblogs.com/sstealer/p/11123666.html
Copyright © 2011-2022 走看看