フリップゲーム(2021-TRN1-K)

フリップゲーム(2021-TRN1-K)

一般的なアイデア

ポータル

これは、
チェスの駒が4 * 4のチェス盤(チェス盤と呼びましょう)の各グリッドに配置されるという点で、poj 1222(実際、質問は少し難しい)に少し似ています。チェスの駒は特別で、片面は黒、もう片面は白です。チェスの駒の色は、チェスの駒をひっくり返すことで変更できます。ピースを裏返すたびに、ピースの色が変わる必要があり、それに応じてピースの周りのピースの色も変わります。
最小限の手順を探します。

問題分析

一般的なDFSは、あまり多くのプルーニングを必要としません。DFSの本質は列挙型であるため、この結論が導き出されます。明らかに、各チェスの駒を開くか開かないかを選択でき、合計2 ^ 16の可能性があります。計算量は非常に少ないです。poj 1222のグリッドが増えると、暴力的なDFSが時間外になる可能性があります。
列挙する方法は?左から右、上から下です。開かれた場合と開かれていない場合の2つのケースが列挙されます。この種の列挙は前代未聞ではありません。その後、バックトラックします。

しかし、それをやったときはまだ苦労していました。チェスの駒の一部が開かないことに気づきませんでした。また、しばらくの間DFSを作成しました。手が生まれました。ステップも関数パラメーターとして使用されます。それ以外の場合は最初にさかのぼる必要がありますか?はっきりと考えていなかった、人がいなくなった。

コード

#include <bits/stdc++.h>

using namespace std;
int a[5][5];
char str[5][5];
int dir[4][2]={
    
    {
    
    1,0},{
    
    0,1},{
    
    -1,0},{
    
    0,-1}};
int mini=1e8;
int check()
{
    
    
    int i,j,sum=0;
    for(i=1;i<=4;i++)
    {
    
    
        for(j=1;j<=4;j++)
        {
    
    
            sum+=a[i][j];
        }
    }
    if(sum==0||sum==16) return 1;
    return 0;
}
void flip(int x,int y)
{
    
    
    a[x][y]^=1;
    for(int k=0;k<4;k++)
    {
    
    
        int newx=x+dir[k][0];
        int newy=y+dir[k][1];
        if(newx>=1&&newx<=4&&newy>=1&&newy<=4)
        {
    
    
            a[newx][newy]^=1;
        }
    }
}
void dfs(int x,int y,int step)
{
    
    
    if(step>16) return;///16个格子都翻过了,不用继续深搜
    if(check())
    {
    
    
        if(step<mini) mini=step;
        return;
    }
    if(y>=5)
    {
    
    
        x++;
        y=1;
    }
    if(x>=5) return;

    flip(x,y);
    dfs(x,y+1,step+1);///翻开棋子
    flip(x,y);///回溯

    dfs(x,y+1,step);///不翻开棋子
}
void init()
{
    
    
    int i,j;
    for(i=1;i<=4;i++)
    {
    
    
        for(j=0;j<4;j++)
        {
    
    
            if(str[i][j]=='b') a[i][j+1]=1;
            else a[i][j+1]=0;
        }
    }
}
int main()
{
    
    
    int i;
    for(i=1;i<=4;i++)
    {
    
    
        gets(str[i]);
    }
    init();
    dfs(1,1,0);
    if(mini<=16) printf("%d\n",mini);
    else printf("Impossible\n");
    return 0;
}

おすすめ

転載: blog.csdn.net/booniebears/article/details/112971282