NOJ——[1264] Flandre\'s First Escape

  • 问题描述
  • Flandre Scarlet is a lovely vampire. However, She owns a very dangerous ability that can destroy all the things in front of her, Not in purpose but carelessly , she uses it sometimes, so she was trapped in the basement for a long period of time and always stay alone.  
    Now, she hopes to see the outwards world, she decides to escape from the basement, thougt it's not an easy task. In order to prevent her from escape, There are many traps in the basement.
    There are many levels in the basement.
    Level one is the same as a game that we always call "Flip Game".  
    Now, let me introduce the rules of this level to you.


    It is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is "#" and the other one is "*" and each piece is lying either it's "#" or "*" side up. Each round you flip 3 to 5 pieces, thus changing the color of their upper side from "#" to "*" 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:  


    **##
    ##*#
    **##
    *#*#


    If we choose to flip the 2st piece from the 3rd row (this choice is shown at the picture), then the field will become:  


    ***#
    #*#*
    ***#
    *#*#  

    The goal of the Level one is to flip either all pieces "#" side up or all pieces "*" side up.  
    Flandre is need your help urgently! You are to write a program that will search for the minimum number of rounds needed to achieve this goal.  
  • 输入
  • There are multiple test cases. The input consists of 4 lines with 4 characters "#" or "*" each that denote game field position.
  • 输出
  • Write the output file a single integer number - the minimum number of rounds needed achieve the goal of the game from the given position.
    If the goal is initially achieved, then write 0. If it's impossible achieve the goal, then write the word "Sorry,I can not help you ..> <.."on one line (without quotes).
  • 样例输入
  • **##
    ##*#
    **##
    *#*#
    *##*
    **#*
    *##*
    *###
    *##*
    **#*
    *##*
    *#**
  • 样例输出
  • Sorry,I can not help you ..> <..
    4
    Sorry,I can not help you ..> <..
  • 提示
  • 来源
  • Minary

一类高消解异或方程的题目。

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>

using namespace std;

const int maxn=500;
int x[maxn];//存最后的解
int mat[maxn][maxn];
int free_x[maxn];//存自由变元

int Gauss(int equ,int var)
{
int i,j,k;
int free_index,free_num;
int max_r,col,num;
col=0;
num=0;
for(k=0;k<equ && col<var;k++,col++)
{
max_r=k;//找到col列上绝对值最大的那行(k行的下面那些行)
for(i=k+1;i<equ;i++)
{
if(abs(mat[i][col]) > abs(mat[max_r][col]))
max_r=i;
}
if(max_r!=k)//找到后和第k行交换
{
for(j=k;j<var+1;j++)
swap(mat[k][j],mat[max_r][j]);
}
if(!mat[k][col])
{
k--;
free_x[num++]=col;//如果第k行第col这个数为0,也就是系数为0,那他就是个自由变量
continue;
}
for(i=k+1;i<equ;i++)
{
if(mat[i][col])
{
for(j=col;j<var+1;j++)
mat[i][j]^=mat[k][j];//异或以后消去k+1行到最后一行的第col列的系数,形成上三角矩阵
}
}
}
for(i=k;i<equ;i++)
if(mat[i][col])
return -1;//无解
//接下来得枚举自由变元
int all=1<<(var-k);//var-k个自由变元,那么有2的指数次个状态
int res=0x3f3f3f3f;
for(i=0;i<all;i++)
{
int cnt=0;
int index=i;
for(j=0;j<var-k;j++)
{
x[free_x[j]]=(index&1);
if(index&1)//如果是1,则要反转,也就是要操作一次
cnt++;
index>>=1;
}
//同时还要判断确定的变量
for(j=k-1;j>=0;j--)
{
int temp=mat[j][var];
for(int l=j+1;l<var;l++)
if(mat[j][l])
temp^=mat[j][l]*x[l];
x[j]=temp;
if(x[j])
cnt++;
}
if(cnt < res)
res = cnt;
}
return res;
}

char str1[30][30];

void unit()
{
memset(mat,0,sizeof(mat));
memset(x,0,sizeof(mat));
memset(free_x,1,sizeof(free_x));
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
{
int t=i*4+j;
mat[t][t]=1;
if(i>0)
mat[(i-1)*4+j][t]=1;
if(i<3)
mat[(i+1)*4+j][t]=1;
if(j>0)
mat[i*4+j-1][t]=1;
if(j<3)
mat[i*4+j+1][t]=1;
}
}

int main()
{
int t;
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
// scanf("%d",&t);
while(~scanf("%s",str1[0]))
{
for(int i=1;i<4;i++)
scanf("%s",str1[i]);
unit();
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(str1[i][j]=='*')
mat[i*4+j][16]=0;
else
mat[i*4+j][16]=1;
}
}
int res1=Gauss(16,16);
unit();
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(str1[i][j]=='#')
mat[i*4+j][16]=0;
else
mat[i*4+j][16]=1;
}
}
int res2=Gauss(16,16);
if(res1<0 && res2<0)
printf("Sorry,I can not help you ..> <..\n");
else
printf("%d\n",min(res1,res2));
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值