Flip Game【POJ--1753】【枚举】【高斯消元】

本文深入探讨了游戏开发领域的关键技术,包括游戏引擎、编程语言、硬件优化等,并重点阐述了AI音视频处理的应用场景和实现方法,如语义识别、语音识别、AR增强现实等。通过实例分析,揭示了这些技术如何提升游戏体验和互动性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each round you flip 3 to 5 pieces, thus changing the color of their upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following rules:
  1. Choose any one of the 16 pieces.
  2. Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).

Consider the following position as an example:

bwbw
wwww
bbwb
bwwb
Here "b" denotes pieces lying their black side up and "w" denotes pieces lying their white side up. If we choose to flip the 1st piece from the 3rd row (this choice is shown at the picture), then the field will become:

bwbw
bwww
wwwb
wwwb
The goal of the game is to flip either all pieces white side up or all pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.

题意:一个4*4的棋盘,每个位置都有一个棋子,每个位置上的棋子可能是白色也可能是黑色,任意给你一盘已经摆放好的棋子,让你去翻动棋子使该整盘棋子变成全部是黑棋或白棋,当你任意翻动一个棋子时,它周围(上下左右)的棋子也跟着翻动(边界处的棋子只是其周围合法的棋子翻动),问你使得该盘棋子全变白或黑最少需要翻动几个棋子。

思路:因为这只是一个4*4的棋盘,用枚举的方法翻动棋子最多翻动2^16次,所以完全可以用枚举的方法来做该题。   
         1.将棋盘的黑白棋数字化。以1代表黑棋以0代表白棋,然后将棋盘上的01数字按行转化成整数。因为这个题输
            入 时是以字符串的形式输入的,直接对字符串进行翻动是不方便的,所以将输入的同时直接将其数字化,最
            后将整个棋盘的值转化为一个整数。
         2.求最短路径用BFS。因为翻动每个位置对应的整数都不一样,所以直接看翻动完之后的值是否满足题目要
            求(如果全盘为黑棋,棋盘的值为2^16-1=65535;如果全盘为白棋,棋盘的值为0).
         3.利用对整数的异或来进行对棋盘棋子的翻转。
    

Input

The input consists of 4 lines with 4 characters "w" or "b" each that denote game field position.

Output

Write to the output file a single integer number - the minimum number of rounds needed to achieve the goal of the game from the given position. If the goal is initially achieved, then write 0. If it's impossible to achieve the goal, then write the word "Impossible" (without quotes).

Sample Input

bwwb
bbwb
bwwb
bwww

Sample Output

4

<span style="font-size:18px;">#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;
int vis[65540];                         //记录到达当前值的步数
int jude(int sum,int i)             //通过异或获得当前棋盘的值
{
    sum^=1<<(15-i);                  //先是翻动当前棋子
    if(i-4>=0)                              //如果上(下)方有合法的棋子(即当前棋子不是边界棋子)则翻动上(下)方棋子
        sum^=1<<(15-i+4);
    if(i+4<=15)                           
        sum^=1<<(15-i-4);
    if(i!=0&&i!=4&&i!=8&&i!=12)     //如果左(右)方有合法的棋子(即当前棋子不是边界棋子)则翻动左(右)方棋子
        sum^=1<<(15-i+1);
    if(i!=3&&i!=7&&i!=11&&i!=15)
        sum^=1<<(15-i-1);
    return sum;                          //返回翻动棋子后棋盘的值
}
void bfs(int sum)                       //求解最少步数
{
    memset(vis,0,sizeof(vis));   
    queue<int>s;
    s.push(sum);             
    while(!s.empty())
    {
        int x=s.front();
        s.pop();
        if(x==0||x==65535)            //如果当前值已符合题目要求就输出到当前值的步数
        {
            printf("%d\n",vis[x]);
            return ;
        }
        for(int i=0;i<16;i++)             //如果当前值不符合,就对当前值(当前棋盘)进行异或(挨个翻动棋子)
        {
            int q=jude(x,i);                //翻动棋子后的棋盘值
            if(!vis[q])
            {
                vis[q]=vis[x]+1;
                s.push(q);
            }
        }
    }
    printf("Impossible\n");
}
int main()
{
    char st[10];
    int cnt=0;
    for(int i=0;i<4;i++)
    {
        scanf("%s",st);
        for(int j=0;j<4;j++)                      //将输入的棋盘数字化,转换成一个整数值
            cnt=(cnt<<1)+(st[j]=='b'?0:1);
    }
    bfs(cnt);    
    return 0;
}</span>

后续:

方法二:用高斯消元求解。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 20
using namespace std;
int equ,var,x[maxn],a[maxn][maxn],free_x[maxn],free_num;
int Gauss()
{
    int max_r,col,k;
    free_num=0;
    for(k=0,col=0; k<equ&&col<var; k++,col++)
    {
        max_r=k;
        for(int i=k+1; i<equ; i++)
            if(a[i][col]>a[max_r][col])
                max_r=i;
        if(!a[max_r][col])
        {
            k--;
            free_x[free_num++]=col;
            continue;
        }
        if(max_r!=k)
        {
            for(int i=col; i<var+1; i++)
                swap(a[max_r][i],a[k][i]);
        }
        for(int i=k+1; i<equ; i++)
        {
            if(a[i][col])
                for(int j=col; j<var+1; j++)
                    a[i][j]^=a[k][j];
        }
    }
    for(int i=k; i<equ;i++)
        if(a[i][col]!=0)
            return -1;
    if(k<var)
        return var-k;
    for(int i=var-1; i>=0; i--)
    {
        x[i]=a[i][var];
        for(int j=i+1; j<var; j++)
            x[i]^=(a[i][j]&&x[j]);
    }
    return 0;
}
void init()
{
    memset(a,0,sizeof(a));
    memset(x,0,sizeof(a));
    equ=16;
    var=16;
    for(int i=0; i<4; i++)
        for(int j=0; j<4; j++)
        {
            int t=i*4+j;
            a[t][t]=1;
            if(i>0)a[(i-1)*4+j][t]=1;
            if(i+1<4)a[(i+1)*4+j][t]=1;
            if(j>0)a[i*4+j-1][t]=1;
            if(j+1<4)a[i*4+j+1][t]=1;
        }
}
int solve()
{
    int t=Gauss(),ans;
    if(t==-1)
    {
        return -1;
    }
    else if(t==0)
    {
        ans=0;
        for(int i=0; i<16; i++)
            ans+=x[i];
    }
    else
    {
        ans=0x3f3f3f3f;
        int tot=1<<(t);
        for(int i=0; i<tot; i++)
        {
            int cnt=0;
            for(int j=0; j<t; j++)
            {
                if(i&(1<<j))
                {
                    x[free_x[j]]=1;
                    cnt++;
                }
                else
                    x[free_x[j]]=0;
            }
            for(int j=var-t-1; j>=0; j--)
            {
                int idx;
                for(idx=j; idx<var; idx++)
                    if(a[j][idx])
                        break;
                x[idx]=a[j][var];
                for(int l=idx+1; l<var; l++)
                    x[idx]^=(a[j][l]&&x[l]);
                cnt+=x[idx];
            }
            ans=min(ans,cnt);
        }
    }
    return ans;
}
char ch[10][10];
<span style="font-family:KaiTi_GB2312;font-size:24px;color:#CC66CC;"></span><pre name="code" class="cpp"><span style="font-family:KaiTi_GB2312;">//</span><span style="font-size:18px;">因为<span style="font-family:KaiTi_GB2312;">该题符合要求的有两个答案(一个是全为1,一个是全为0),所以要用两次高斯消元求两次解,最后取最小值</span></span>
 int main(){ init(); for(int i=0; i<4; i++) { scanf("%s",ch[i]); for(int j=0; j<4; j++) { if(ch[i][j]=='b') a[i*4+j][16]=1; else a[i*4+j][16]=0; } } int cnt1=solve(); init(); for(int i=0; i<4; i++) for(int j=0; j<4; j++) { if(ch[i][j]=='b') a[i*4+j][16]=0; else a[i*4+j][16]=1; } int cnt2=solve(); if(cnt1==-1&&cnt2==-1) printf("Impossible\n"); else printf("%d\n",min(cnt1,cnt2)); return 0;}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值