题意就是说:翻牌,随便翻到一张牌,其上下左右随他都得翻,看最少用翻几张牌,能够让16张牌全为正或全为负。

这道题有一个大坑,就是每一张牌其实只能翻奇数次,比如翻的顺序为 (3,2)->   (2,2)  ->  (3,2)   = =   (2,2)  是  等价的

故最多翻的个数是16,从0到16一个一个测试,枚举的是翻牌的个数,若全为正或反,则断开枚举,否则一直枚举

最多有C(0,16)+C(1,16)+。。。+C(16,16)=2^16次,

这道题首先是用dfs码的,但是最麻烦的情况下会超时吧,比如Impossible;//不会改,我只是一名小牛

后来用枚举翻牌个数打的,期间遇到很多问题;

1:二维变一维,在翻牌时要注意关联牌的翻转;

2:一般组合代码的实现,即16个牌中抽n个牌的代码n>=0,n<=16;

3:  翻牌后若不为全,还得翻回来;//其实可以把实参数组传递给形参解决;



一般组合组合的代码如下:省略打的

int n,m;
cin>>n>>m;
int rcd[10];
int num[10];
void select_combination(int l,int p)
{
    int i;
    if(l==m)
    {
       for(i=0;i<m;i++) 
       {
           cout<<rcd[i];
           if(i<m-1)
            cout<<' ';
       }
       cout<<endl;
       return ;
    }
    for(i=p;i<n;i++)
    {
        rcd[l]=num[i];
        select_combination(int l+1,int i+1)
    }
}
int mian()
{
    select_combination(0,0);
    return 0;
}

下面是我打的代码:

    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    char a[5][5];//二维
    char own[30];//一维
    int add[6]= {0,4,-4,1,-1};//翻转区域
    //queue<int> s;
    int num[30];
    int point;//
    int k=0;
    int n=16;
    int find()//发现是否出现全为0或全为1
    {
        int i;
        int k1=1,k2=1;
        for(i=0; i<16; i++) //判断是否全为黑色
        {
            if(own[i]=='0')//有白色
            {
                k1=0;
            }
            if(own[i]=='1')//有黑色
            {
                k2=0;
            }
        }
        if(k1==0&&k2==0)//既有白,又有黑
        {
            return -1;
        }
        else
            return 0;//全
    }
    int tell(int i)//判断是否出界
    {
        if(i<0||i>=16)
            return 0;
        else
            return 1;
    }
    void fanzhuan(int k)//进行翻转
    {
        int p;
        int i;
        for(i=0; i<3; i++)
        {
            p=k+add[i];
            if(tell(p)==1)
            {
                if(own[p]=='1')
                    own[p]='0';
                else
                    own[p]='1';
            }
        }
        int x=k%4;
        if(x==0)
        {
          p=k+1;
            if(tell(p)==1)
            {
                if(own[p]=='1')
                    own[p]='0';
                else
                    own[p]='1';
            }
        }
        else if(x==3)
        {
             p=k-1;
             if(tell(p)==1)
            {
                if(own[p]=='1')
                    own[p]='0';
                else
                    own[p]='1';
            }
        }
        else
        {
           for(i=3;i<5;i++)
           {
               p=k+add[i];
               if(tell(p)==1)
               {
                if(own[p]=='1')
                    own[p]='0';
                else
                    own[p]='1';
               }
           }

        }
    }
    int panduan()
    {
        int i,j;
        for(i=0; i<point; i++)
        {
            int p=num[i];
            fanzhuan(num[i]);
        }
        if(find()==0)//全
            return 1;
        else
            return 0;
    }
    void  select_com(int l,int p)
    {
        int i;
        if(l==point)
        {
            int g=panduan();
            if(g==1)
            {
                k=1;
                cout<<point<<endl;
                return ;
            }
            else
            {
                int t=panduan();
            }
        }
        for(i=p; i<n; i++)
        {
            if(k==0)
            {
                num[l]=i;
                select_com(l+1,i+1);
            }
        }
    }
    int main()
    {
        while(cin>>a[0][0])
        {
            int i,j;
            int start=0;
            for(i=1; i<=3; i++)
            {
                cin>>a[0][i];
            }
            for(i=0; i<4; i++)
            {
                if(a[0][i]=='b')
                    a[0][i]='1';
                else
                    a[0][i]='0';
                own[start++]=a[0][i];
            }
            for(i=1; i<=3; i++)
            {
                for(j=0; j<4; j++)
                {
                    cin>>a[i][j];
                    if(a[i][j]=='b')//黑色
                        a[i][j]='1';
                    else//白色
                        a[i][j]='0';
                    own[start++]=a[i][j];//二维变一维
                }
            }
            int m=1;
            if(find()==0)
                cout<<0<<endl;
            else//枚举翻转个数m
            {
                while(m<16)
                {
                    point=m;
                    select_com(0,0);
                    if(k==1)
                        break;
                    m++;
                }
                if(k==0)
                    cout<<"Impossible"<<endl;
            }
            k=0;
        }
        return 0;
    }





测试案例如下:
代码已AC

bwbw
wwww
bbwb
bwwb
Impossible

bwwb
bbwb
bwwb
bwww
4

wwww
wwww
wwww
wwww
0

bbbb
bbbb
bbbb
bbbb
0

bbbb
bwbb
bbbb
bbbb
Impossible

bwbb
bwbb
bwbb
bbbb
Impossible

bwbb
wwwb
bwbb
bbbb
1

wwww
wwwb
wwbb
wwwb
1

wwww
wwww
wwwb
wwbb
1

wbwb
bwbw
wbwb
bwbw
Impossible

bbbb
bwwb
bwwb
bbbb
4

bwwb
wbbw
wbbw
bwwb
4

bbww
bbww
wwbb
wwbb
Impossible

bbwb
bbbw
wwbb
wwwb
Impossible

wwwb
wwbw
wbww
wwbw
Impossible

bbbb
wwww
wwbb
wbbb
Impossible

bwwb
wbwb
wbbb
wbbb
4

bwbb
bwbb
bwbw
bbbw
5

wbwb
bbbb
bbww
wbbb
6

bbwb
bbbb
wbwb
bbbb
5






Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐