1. 程式人生 > >poj 1753 2965

poj 1753 2965

這兩道題類似,前者翻轉上下左右相鄰的棋子,使得棋子同為黑或者同為白。後者翻轉同行同列的所有開關,使得開關全被開啟。

題意:有一4x4棋盤,上面有16枚雙面棋子(一面為黑,一面為白), 當翻動一隻棋子時,該棋子上下左右相鄰的棋子也會同時翻面。以b代表黑麵,w代表白麵,給出一個棋盤狀態,     問從該棋盤狀態開始,使棋盤變成全黑或全白,至少需要翻轉多少步

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int mp[5][5];
int step,flag;
int range()//遍歷整個棋盤是否“清一色”
{
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            if(mp[i][j]!=mp[0][0])
                return 0;
    return 1;
}
void turn(int i,int j)//翻轉(i,j)棋子,以及(i,j)周圍的棋子
{
    mp[i][j]=!mp[i][j];
    if(i>0) mp[i-1][j]=!mp[i-1][j];
    if(i<3) mp[i+1][j]=!mp[i+1][j];
    if(j>0) mp[i][j-1]=!mp[i][j-1];
    if(j<3) mp[i][j+1]=!mp[i][j+1];
}
int dfs(int i,int j,int k)
{
    if(k==step){
        flag = range();
        return 0;
    }
    if(flag||i==4){
        return 1;
    }
    turn(i,j);
    if(j<3) dfs(i,j+1,k+1);//一行當中的所有列
    else dfs(i+1,0,k+1);//下一行
    turn(i,j);//回溯,翻回來
     if(j<3) dfs(i,j+1,k);//下一個棋子繼續dfs
    else dfs(i+1,0,k);
    return 0;
}
int main()
{
    char str[5][5];
    for(int i=0;i<4;i++)
        cin>>str[i];
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            if(str[i][j]=='b') mp[i][j]=1;
            else mp[i][j]=0;
    for(step=0;step<=16;step++)
    {
        flag = 0;
        dfs(0,0,0);//(x,y),step
        if(flag) break;
    }
    if(flag) printf("%d\n",step);
    else printf("Impossible\n");
    return 0;
}