POJ1222 - EXTENDED LIGHTS OUT(熄灯问题)(二进制枚举)

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zxzxzx0119/article/details/85069013

POJ1222 - EXTENDED LIGHTS OUT(熄灯问题)(二进制枚举)


题目链接

题目大意

有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。

对矩阵中的每盏灯设置一个初始状态。请你按按钮,直至每一盏等都熄灭。与一盏灯毗邻的多个按钮被按下时,一个操作会抵消另一次操作的结果。

Sample Input
5行组成,每一行包括6个数字(01)。相邻两个数字之间用单个空格隔开。0表示灯的初始状态是熄灭的,1表示灯的初始状态是点亮的。

2
0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0
0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 0 1 1 0 0
0 1 0 1 0 0

Sample Output
5行组成,每一行包括6个数字(01)。相邻两个数字之间用单个空格隔开。其中的1表示需要把对应的按钮按下,0则表示不需要按对应的按钮。

PUZZLE #1
1 0 1 0 0 1
1 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
0 1 0 0 0 0
PUZZLE #2
1 0 0 1 1 1
1 1 0 0 0 0
0 0 0 1 0 0
1 1 0 1 0 1
1 0 1 1 0 1

解析

如果枚举每一个格子的每两个状态,就会有230种状态,会超时。

正确的做法是只需要枚举第一行的状态,然后依次往下面去影响下面的行,只枚举一行的话,只需要26 = 64种状态,可以使用二进制枚举的方式来进行枚举:

  • 使用一个字符数组保存每一行的一个状态即可,因为这个数最大不会超过 26,每一个字符保存的是一行的状态,因为可以使用一行6位来确定这个字符;
  • 设定三个函数getBitsetBitflipBit分配来获取字符的第i位、设置字符的第i位、翻转字符的第i位。
  • 然后按照枚举每一行,然后去影响旁边和下一行的方式,总共枚举64种即可,如果枚举到第5行,这一行的灯都是0(灭)的话,这个方案就可以,记得使用一个字符数组记录结果,最后打印即可。
import java.io.*;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Main {

    private static int getBit(char c, int i){
        return (c >> i) & 1;
    }
    private static void setBit(char[] lights, int i, int j, int val){
        lights[i] = (char) (val == 1 ? lights[i]|(1<<j): lights[i]&(~(1<<j)));
    }
    private static void flipBit(char[] lights, int i, int j){
        lights[i] ^= (1 << j);
    }
    private static void printResult(int t, char[] res, PrintWriter out){
        out.println("PUZZLE #" + t);
        for(int i = 0; i < 5; ++i){
            for(int j = 0; j < 6; ++j){
                out.print(getBit(res[i], j));
                if(j < 5)
                    out.print(" ");
            }
            out.println();
        }
    }
    private static void solve(FastReader in, PrintWriter out){
        char[] oriLight = new char[5];
        char[] lights = new char[5];
        char[] res = new char[5];
        int T, num;
        T = in.nextInt();
        for(int t = 1; t <= T; ++t) {
            for (int i = 0; i < 5; ++i) {
                for (int j = 0; j < 6; ++j) {
                    num = in.nextInt();
                    setBit(oriLight, i, j, num);
                }
            }

            for(int n = 0; n < 64; n++) {
                int switchs = n;
                System.arraycopy(oriLight, 0, lights, 0, oriLight.length);
                for (int i = 0; i < 5; ++i) {
                    res[i] = (char) switchs;
                    for (int j = 0; j < 6; ++j) {
                        if (1 == getBit((char)switchs, j)) {
                            flipBit(lights, i, j);
                            if (j > 0)
                                flipBit(lights, i, j - 1);
                            if (j < 5)
                                flipBit(lights, i, j + 1);
                        }
                    }
                    if(i < 4)
                        lights[i+1] ^= switchs;
                    switchs = lights[i];
                }
                if (lights[4] == 0) {
                    printResult(t, res, out);
                    break;
                }
            }
        }
    }

    private static class FastReader{
        public BufferedReader br;
        public StringTokenizer st;

        public FastReader(InputStream is){
            br = new BufferedReader(new InputStreamReader(is));
            st = null;
        }

        String next(){
            while(st == null || !st.hasMoreElements()){
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        public int nextInt(){
            return Integer.parseInt(next());
        }
        public long nextLong(){
            return Long.parseLong(next());
        }
        public double nextDouble(){
            return Double.parseDouble(next());
        }
        public String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }

    public static void main(String[] args){
//        Scanner fr = new Scanner(new BufferedInputStream(System.in));
//        try {
//            fr = new Scanner(new FileInputStream("/home/zxzxin/Java_Maven/Algorithm/src/main/java/ACM/Other/in.txt"));
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }
        // more fast
        FastReader fr = new FastReader(new BufferedInputStream(System.in));
       // try {
       //     fr = new FastReader(new FileInputStream("/home/zxzxin/Java_Maven/Algorithm/src/main/java/ACM/Other/in.txt"));
       // } catch (FileNotFoundException e) {
       //     e.printStackTrace();
       // }
        PrintWriter out = new PrintWriter(System.out);
        long start = System.nanoTime();
        solve(fr, out);
        long end = System.nanoTime();
        //System.out.println("Time elapsed: " + (end - start)/1000000000.0);
        out.close();
    }
}

C++代码:

#include <iostream>
#include <string.h>

int getBit(char c, int i){ //取c的第i位 
    return (c>>i) & 1; 
}

void setBit(char &c, int i, int val){ //给c的第i位设置成val(0/1) 
    c = val ? c|(1<<i) : c&(~(1<<i));
}

void flipBit(char &c, int i){  // 将c的第i位翻转 
    c ^= (1 << i); //不同为1相同为0, 原先是1 ^ 1--> 0, 原先是0^1 --> 1 
}

void printResult(int t, const char* res){ 
    std::cout << "PUZZLE #" << t << std::endl;
    for(int i = 0; i < 5; i++){ 
        for(int j = 0; j < 6; j++){ 
            std::cout << getBit(res[i], j);
            if(j < 5)
                std::cout << " ";
        }
        std::cout << std::endl;
    }
}

int main(int argc, char const** argv)
{ 
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    int T, num;
    char oriLights[5], lights[5], res[5];
    std::cin >> T;
    for(int t = 1; t <= T; t++){ 
        for(int i = 0; i < 5; i++){  // 5 row
            for(int j = 0; j < 6; j++){  // 6 col
                std::cin >> num;
                setBit(oriLights[i], j, num);
            }
        }
        // 枚举当前的行,去处理下面的行,二进制枚举总共有2^6 = 64 
        for(int n = 0; n < 64; n++){ 
            int tmpN = n;  // cur row's result 
            memcpy(lights, oriLights, sizeof(oriLights));
            for(int i = 0; i < 5; i++){ 
                res[i] = tmpN; // record the result
                for(int j = 0; j < 6; j++){ 
                    if(getBit(tmpN, j)){  //judge curPosition is 1, to influence next to self
                        flipBit(lights[i], j); // self filp
                        if(j > 0)
                            flipBit(lights[i],j-1); // left filp
                        if(j < 5)
                            flipBit(lights[i],j+1);  // right flip
                    }
                }
                //curRows influence next row (important) ---> down flip 
                if(i < 4)  // 5 rows in total
                    lights[i+1] ^= tmpN;
                tmpN = lights[i]; // update tmpN
            }
            if(lights[4] == 0){
                printResult(t, res);
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxzxzx0119/article/details/85069013