#0x08 飞行员兄弟 (枚举+位运算)

题解:

  • 这道题第一眼和前面的最短哈密顿路径很相似,但是不太相同。这道题数据不大,可以朴素枚举每行的所有情况,用二进制压缩表示每行的各种情况,也就是0 ~ 1<<4种。
  • 对于每组情况,每次操作完后,最后要重复操作一次,因为可以发现规律,两次相同的操作可以抵消掉这次操作,对以后的操作没有影响。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MA=1e2+5;

int a[6][6],l[5];
struct node{
    int x,y;
};

vector<node> ans;

void change(int x,int y){
    for(int i=1;i<=4;++i) a[x][i]^=1;
    for(int i=1;i<=4;++i) a[i][y]^=1;
    a[x][y]^=1;
}

void solve(int x,int y){
    int i=0;
    while(i<4){
        if(y>>i &1){
            change(x,4-i);
        }
        i++;
    }
}

bool check()
{
    for(int i=1;i<=4;++i){
        for(int j=1;j<=4;++j)
            if(!a[i][j]) return false;
    }
    return true;
}

bool cmp(const node &b,const node &c){
    if(c.x==b.x) return b.y<c.y;
    else return b.x<b.x;
}

void print()
{
    node e;
    for(int i=1;i<=4;++i){
        int j=0;
        while(j<4){
            if(l[i]>>j &1){
                e.x=i,e.y=4-j;
                ans.push_back(e);
            }
            j++;
        }
    }
    sort(ans.begin(),ans.end(),cmp);
    printf("%d\n",ans.size());
    for(int i=0;i<ans.size();++i){
        printf("%d %d\n",ans[i].x,ans[i].y);
    }
}

int main()
{
    for(int i=1;i<=4;++i){
        char s[5];
        scanf("%s",&s);
        for(int j=1;j<=4;++j){
            a[i][j]=(s[j-1]=='-') ? 1 : 0;
        }
    }
    for(l[1]=0;l[1]< 1<<4;++l[1]){
        solve(1,l[1]);
        for(l[2]=0;l[2]< 1<<4;++l[2]){
            solve(2,l[2]);
            for(l[3]=0;l[3]< 1<<4;++l[3]){
                solve(3,l[3]);
                for(l[4]=0;l[4]< 1<<4;++l[4]){
                    solve(4,l[4]);
                    if(check()){
                        print();
                        return 0;
                    }
                    solve(4,l[4]);

                }
                solve(3,l[3]);
            }
            solve(2,l[2]);
        }
        solve(1,l[1]);
    }
    return 0;
}

posted @ 2020-02-04 09:16  A_sc  阅读(137)  评论(0)    收藏  举报