1. 程式人生 > >1753 Flip Game dfs

1753 Flip Game dfs

題目連結

題意:一個4*4的棋盤,每個格子上有一個黑白棋(黑色朝上或白色朝上),定義操作翻轉某個位置的棋子,同時也翻轉其上下左右四個棋子,求把整個棋盤翻轉成都是白色朝上或者黑色朝上的最少步數。

思路:對於某個位置的棋子,我們可以看出翻2次和不翻效果是一樣的,翻3次效果和翻1次效果一樣,所以對於每個位置只有兩種情況:翻1次或者不翻,同時翻的順序對結果也並沒有影響,由此,假設我們已經找到一種翻第一行棋子的策略,那麼要滿足最後是同種顏色朝上,那麼第二行的翻轉策略已經固定只有兩種(一種使第一行白色朝上,一種使第一行黑色朝上),以此類推,所以我們只要列舉第一行的翻轉策略就行了。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
#include<deque>
#define ll long long
#define PI acos(-1)
#define INF 0x3f3f3f3f
#define NUM 500020
#define debug true
#define lowbit(x) ((-x)&x)
#define ffor(i,d,u) for(int i=(d);i<=(u);++i)
#define _ffor(i,u,d) for(int i=(u);i>=(d);--i)
#define mst(array,Num,Kind,Count) memset(array,Num,sizeof(Kind)*(Count))
using std::min;
const int P = 1e9+7;
bool ch[5][5],ch1[5][5];
int ans;
template <typename T>
void read(T& x)
{
    x=0;
    char c;T t=1;
    while(((c=getchar())<'0'||c>'9')&&c!='-');
    if(c=='-'){t=-1;c=getchar();}
    do(x*=10)+=(c-'0');while((c=getchar())>='0'&&c<='9');
    x*=t;
}
template <typename T>
void write(T x)
{
    int len=0;char c[21];
    if(x<0)putchar('-'),x*=(-1);
    do{++len;c[len]=(x%10)+'0';}while(x/=10);
    _ffor(i,len,1)putchar(c[i]);
}
inline void turn(bool &x)
{
    x = !x;
}
inline bool check(bool flag)
{
    ffor(i,1,4)if(ch[4][i] != flag)return false;
    return true;
}
int tryy(int line,bool flag,int step)
{
    if(line == 5)return (check(flag)?step:INF);
    ffor(i,1,4)
        if(ch[line-1][i] != flag)
        {
            ch[line-1][i] = flag;
            if(i > 1)turn(ch[line][i-1]);
            turn(ch[line][i]);
            if(i < 4)turn(ch[line][i+1]);
            if(line < 4)turn(ch[line+1][i]);
            ++step;
        }
    return tryy(line+1,flag,step);
}
int solve(bool flag)
{
    int ans = INF,step,x;
    int a[5];
    ffor(i,0,15)
    {
        x = i;
        ffor(j,1,4)ch[1][j] = ch1[1][j],a[j] = x%2,x /= 2;
        ffor(i,2,4)ffor(j,1,4)ch[i][j] = ch1[i][j];
        step = 0;
        ffor(j,1,4)
        {
            if(a[j] == 0)continue;
            turn(ch[1][j]);
            if(j > 1)turn(ch[1][j-1]);
            if(j < 4)turn(ch[1][j+1]);
            turn(ch[2][j]);
            ++step;
        }
        x = tryy(2,flag,step);
        ans = min(ans,x);
    }
    return ans;
}
inline void AC()
{
    char x;
    ffor(i,1,4)
    {
        ffor(j,1,4)x = getchar(),ch1[i][j] = (x == 'b');
        getchar();
    }
    ans = solve(false);
    ans = min(ans,solve(true));
    if(ans == INF)puts("Impossible");
    else write(ans),putchar('\n');
}
int main()
{
    AC();
    return 0;
}