題解-翻棋子

Cancelleds發表於2020-10-06

Problem H: 翻棋子

Description
有一個4*4的棋盤,放有16枚棋子。
每個棋子都是一面黑一面白,一開始有的黑麵朝上,有的白麵朝上。
下面是一個例子,這個例子用文字描述為:
bwbw
wwww
bbwb
bwwb
我們可以任選一個棋子,把它自己和它的相鄰棋子(上下左右,如果有的話)翻面。
比如在例子中如果我們選第3行第1列的棋子翻面,佈局就變成如下:
bwbw
bwww
wwwb
wwwb
題目
求出能把所有棋子都翻成白色或都黑色的最少的步數。
Input
4行每行4個字元,可能是b(黑)或w(白)
Output
一個數,最少步數。如果無解輸出Impossible
Sample Input
bwbw
wwww
bbwb
bwwb
Sample Output
Impossible
HINT

#include<bits/stdc++.h>
using namespace std;
char ch;
int mp[5][5],ans=0x3f3f3f3f;
const int dir[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}};
bool flag;
int check(int x)
{
    return (x+1)%2;
}
bool in(int x,int y)
{
    return 1<=x&&x<=4&&1<=y&&y<=4;
}
bool check()
{
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
            if(mp[i][j]!=mp[1][1])
                return 0;
    return 1;
}
void fan(int x,int y)
{
    for(int i=0;i<5;i++)
    {
        int tx=x+dir[i][0],ty=y+dir[i][1];
        if(in(tx,ty))
            mp[tx][ty]=check(mp[tx][ty]);
    }
}
void dfs(int step,int x,int y)
{
    if(check())
    {
        ans=min(ans,step);
        flag=1;
        return;
    }
    if(x==5)
        return;
       
    fan(x,y);
    if(y==4)
        dfs(step+1,x+1,1);
    else
        dfs(step+1,x,y+1);
    fan(x,y);
       
    if(y==4)
        dfs(step,x+1,1);
    else
        dfs(step,x,y+1);
    return;
}
int main()
{
    for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
        {
            cin>>ch;
            if(ch=='b')
                mp[i][j]=1;
            else
                mp[i][j]=0;
        }
    dfs(0,1,1);
    if(!flag)
        cout<<"Impossible"<<endl;
    else
        cout<<ans<<endl;
    return 0;
}

相關文章