1. 程式人生 > >費解的開關(二進位制+BFS)

費解的開關(二進位制+BFS)

問題 E: 費解的開關

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 96  解決: 37
[提交] [狀態] [討論版] [命題人:admin]

題目描述

你玩過“拉燈”遊戲嗎?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 

分析:太菜了,根本想不到。BFS還是挺容易想到的,但是用二進位制就想不到了,其實也挺明顯因為只有0和1嘛,還有就是反向BFS由全是1的狀態轉移,記錄存圖記錄步數。

1、首先BFS打表,由(1<<25)-1開始轉移,利用^的性質使0和1轉換。

2、每個狀態的二進位制一共25位,把每一位都列舉到然後進行一次狀態的轉換。記下此時的步數,並且存起來轉換後的數字,以待下一次轉換。

3、map存結果。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<deque>
#include<ctype.h>
#include<map>
#include<set>
#include<stack>
#include<string>
#define INF 0x3f3f3f3f
#define FAST_IO ios::sync_with_stdio(false)
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;
#define gcd(a,b) __gcd(a,b)
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
inline ll inv1(ll b){return qpow(b,mod-2);}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll r=exgcd(b,a%b,y,x);y-=(a/b)*x;return r;}
inline ll read(){ll x=0,f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x*f;}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
map<int,int>mp;
queue<int>q;
int change(int x,int i)
{
    x=x^(1<<i);
    if((i%5)<4)
        x=x^(1<<(i+1));
    if(i%5)
        x=x^(1<<(i-1));
    if(i>=5)
        x=x^(1<<(i-5));
    if(i<20)
        x=x^(1<<(i+5));
    return x;
}
void bfs()
{
    int x=(1<<25)-1;
    mp[x]=1;
    q.push(x);
    while(!q.empty())
    {
        x=q.front();
        q.pop();
        if(mp[x]>6)
            break;

        for(int i=0;i<25;i++)
        {
            int p;
            p=change(x,i);
            if(mp[p])
                continue;

            mp[p]=mp[x]+1;
            q.push(p);
        }
    }
}
int main()
{
    int T;
    bfs();
    scanf("%d",&T);
    while(T--)
    {
        int s=0;
        for(int i=0;i<25;i++)
        {
            int a;
            scanf("%1d",&a);
            s=s+(a<<i);
        }
        printf("%d\n",mp[s]-1);
    }
    return 0;
}