zoukankan      html  css  js  c++  java
  • 费解的开关(状压)

    题目描述

    你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
    我们用数字“1”表示一盏开着的灯,用数字“0”表示关着的灯。下面这种状态
    10111
    01101
    10111
    10000
    11011
    在改变了最左上角的灯的状态后将变成:
    01111
    11101
    10111
    10000
    11011
    再改变它正中间的灯后状态将变成:
    01111
    11001
    11001
    10100
    11011

    给定一些游戏的初始状态,编写程序判断游戏者是否可能在6步以内使所有的灯都变亮。

    输入

    第一行有一个正整数n,代表数据中共有n个待解决的游戏初始状态。
    以下若干行数据分为n组,每组数据有5行,每行5个字符。每组数据描述了一个游戏的初始状态。各组数据间用一个空行分隔。
    对于30%的数据,n<=5;
    对于100%的数据,n<=500。

    输出

    输出数据一共有n行,每行有一个小于等于6的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。
    对于某一个游戏初始状态,若6步以内无法使所有灯变亮,请输出“-1”。 

    样例输入

    3
    00111
    01011
    10001
    11010
    11100
    
    11101
    11101
    11110
    11111
    11111
    
    01111
    11111
    11111
    11111
    11111
    

    样例输出

    3
    2
    -1 

    1.每个位置至多只会被点击一次
    2.若固定了第一行,则满足题意的点击方案至多只有一种。因为当第i行某一位为1时,若前i行已经被固定,只能点击i+1行该位置上的数字才能使第i行的这一位置变成0。

    在图确定的情况下,确定第i行的点击方案,第i+1行的点击方案也随之确定。所以状压枚举第一行所有点击方案,共2⁵ 32种;

    一、用0x3f3f3f3f表示maxn;
    二、用二进制的01表示状态;

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 5;
    const int inf = 0x3f3f3f3f;
    
    char _map[maxn][maxn + 5];
    char sta[maxn][maxn + 5];
    int times, min_times;
    int dx[5] = {-1, 0, 0, 1};
    int dy[5] = {0, 1, -1, 0};
    
    bool check(int x, int y) {
        if (x >= 0 && x < 5 && y >= 0 && y < 5) return 1;
        else return 0;
    }
    
    void press(int x, int y) {
        sta[x][y] = (sta[x][y] == '0') ? '1' : '0';
        for (int i = 0; i < 4; i++) {
            if (check(x + dx[i], y + dy[i]))
                sta[x + dx[i]][y + dy[i]] = (sta[x + dx[i]][y + dy[i]] == '0') ? '1' : '0';
        }
        times++;
    }
    
    int main() {
        int n;
        cin >> n;
        while (n--) {
             min_times = inf;
            for (int i = 0; i < maxn; i++)
                cin >> _map[i];
            for (int i = 0; i < (1 << maxn); i++) {
                times=0;
                memcpy(sta, _map, sizeof(_map));
                int now = i;
                for (int j = 0; now; j++, now >>= 1) {
                    if (now & 1)
                        press(0, j);
                }
                for (int j = 1; j < maxn; ++j) {
                    for (int k = 0; k < maxn; ++k) {
                        if (sta[j - 1][k] == '0')
                            press(j, k);
                    }
                }
                int flag = 1;
                for (int j = 0; j < maxn; j++) {
                    for (int k = 0; k < maxn; ++k) {
                        if (sta[j][k] == '0')
                            flag = 0;
                    }
                }
                if (flag) min_times = min(times, min_times);
            }
            if (min_times > 6) cout << -1 << endl;
            else cout << min_times << endl;
            //cout<<min_times<<endl;
        }
        return 0;
    }
  • 相关阅读:
    UVa 10810
    Android UI开发第三十四篇——SlidingPaneLayout
    eclipse安装插件checkstyle
    eas bos 编辑界面 editUIt 属性值为空
    [置顶] 使用U盘安装ubuntu系统
    Ajax核心——XMLHttpRequest基础
    转储指定的数据块并查看TRC信息
    android 获取当前版本号/修改自定义的应用程序的版本号
    poj3101
    [置顶] mysql中的set和enum类型的用法和区别
  • 原文地址:https://www.cnblogs.com/albert-biu/p/9280541.html
Copyright © 2011-2022 走看看