poj2965 The Pilots Brothers' refrigerator

//题意:同样给你一个4*4的矩阵,但每一个点代表一个开关,开关可开可闭,只有开关全部打开时才有用,你每一次打开或者关闭一个开关会导致与他相同的行的开关以及与他同列的开关反转,问最少多少次可全部打开并且打印顺序,若有多解则任意输出一组反转顺序即可

//思路:和poj1753思路基本一致,不同的地方:1)在这里的中之状态只有一个,全开,而1753有两个全开或者全闭 ;2)此题要求输出这个非常容易,只要判断出是哪一种情况切实最小值时,保存最后简单循环处理输出即可;3)此题的坑在于每次反转重复次数过多,如果每次手动用函数反转必定超时按照1753的思路的话,因此直接打表将16种反转情况达标即可;【注意】:若不懂可先将poj1753弄懂两个题完全一样思路点击打开博主的poj1753。(博主的poj1753 flip函数就是手动反转的过程,此题若手动函数反转会超时,则将所有反转的值直接保存在数组t中即可)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int const len = 16;
char branch[4][4];
int t[16]={63624,62532,61986,61713,36744,20292,12066,7953,35064,17652,8946,4593,34959,17487,8751,4383};

//二进制下标
/*
15 14 13 12
11 10 9  8
7  6  5  4
3  2  1  0
*/

/*
-+--
----
----
-+--
*/

int main()
{
    while(scanf("%s", branch) != EOF){

        int status = 0; //全+为0 全1为#ffff
        int num = len;
        int print;
        int cnt = 20;
        for(int i = 1; i < 4; i++){
            getchar();
            scanf("%s", branch[i]);
        }
        for(int i = 0; i < 4; i++){
            for(int j = 0; j < 4; j++){
                num--;
                if(branch[i][j] == '-')
                    status ^= 1 << num;
            }
        }


        for(int i = 0; i <= 0xffff; i++){
            int status_ = status;   //副本
            int step = 0;
            int index = 15;
            for(int j = 0; j <= 15; j++){
                if((1<<j) & i){
                    status_ ^= t[index];
                    step++;
                }
                if(status_ == 0xffff && step <= 16){
                    if(step < cnt){
                        cnt = step;
                        print = i;
                    }
                }
                index--;
            }
        }

        printf("%d\n", cnt);
        for(int i = 15; i >= 0; i--){
            if((1 << i) & print){
                printf("%d %d\n", 5-(i/4 + 1), 5-(i%4 + 1));//这里需要将输出的下表更改,因为我的二进制下表见上面注释
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值