现在的位置: 首页 > 综合 > 正文

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

2019年02月15日 ⁄ 综合 ⁄ 共 3723字 ⁄ 字号 评论关闭
  • 问题描述
  • 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;
}

抱歉!评论已关闭.