给出一个4*4的字符,+代表close,-代表open,每次可以选择一个字符进行变化。选择坐标(x,y)的字符会导致x行y列都反转。问你最少几次操作能把所有字符变成-。

此题有两种方法:1.枚举+位运算 2.高斯消元

1.暴力枚举每一行,如果此行状态有1就反转这个位置,复杂度24*4=216

代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
typedef long long ll;

int a[5];
char ch;
int flag=0,ans;
vector<pair<int,int> > ma;
void turn(int x,int y)
{
    a[x]=~a[x];
    for(int i=0;i<4;++i)
        if(i!=x) 
            a[i]^=(1<<y);
}
void dfs(int x)
{
    if(flag)
        return ;
    if(x==4){
        for(int i=0;i<4;++i)
            if(a[i]&15) 
                return ;
        cout<<ma.size()<<endl;
        for(int i=0;i<ma.size();++i)
            cout<<ma[i].first<<' '<<4-ma[i].second<<endl;
        flag=1;
    }
    dfs(x+1);
    for(int s=1;s<1<<4;++s){
        int tmp=0;
        int b[4];
        for(int i=0;i<4;++i)b[i]=a[i];
        for(int i=3;~i;--i){
            if(s>>i&1){
                ++tmp;
                ma.push_back(make_pair(x+1,i));
                turn(x,i);
            }
        }
        dfs(x+1);
        while(tmp--)
            ma.pop_back();
        for(int i=0;i<4;++i)a[i]=b[i];
    }
}
int main(int argc, char **argv) {
    for(int i=0;i<4;++i)
        for(int j=3;~j;--j){
            cin>>ch;
            if(ch=='+')
                a[i]|=1<<j;
        }
    dfs(0);
    return 0;
}

2.高斯消元

跟POJ1830的开关问题一样,只不过这里相联系的开关是一行一列。

给出的是初始状态,要求目标状态全是open。

posted on 2018-04-27 09:36  chagin  阅读(107)  评论(0)    收藏  举报