问题描述:
有m*n(1 ≤ m, n ≤ 100)个金币在桌面上排成一个 m 行 n 列的阵列。每一枚金币或正面朝上或背面朝上。用数字表示金币状态,0表示金币正面朝上,1 表示背面朝上。
金币阵列游戏的规则是:
1. 每次可将任一行金币翻过来放在原来的位置上;
2. 每次可任选 2 列,交换这 2 列金币的位置。
本题要求对于给定的金币阵列初始状态和目标状态,编程计算按金币游戏规则,将金币阵列从初始状态变换到目标状态所需的最少变换次数。
数据输入:
输入的测试数据的第一行是一个不超过 10 的正整数 k,表示有 k 个测试用例. 每个测试用例的第一行是两个正整数 m, n. 接下来是 m 行,每行有 n 个用空白符分隔的 0 或 1. 这 m*n 个 0-1 表示金币的初始状态阵列。最后是 m 行,每行 n 个 用空白符分隔的 0 或 1,表示金币阵列的目标状态。
数据输出:
对于每个测试用例,输出一行包含一个整数,表示按照要求规则将金币阵列从初始状态变换为目标状态所需要的最少变换次数。如果不能按照变换规则将初始状态变换为目标状态(即无解时)则输出 -1。
#include<stdio.h>
#define MAX 100
int org[MAX][MAX];
int obj[MAX][MAX];
int need=0;//需要变换的次数
int n,m;
int is_col_equal(int i);
int is_row_equal(int i);
int equal2(int i,int j);//判断org的i列和obj的j列是否一致
int equal_all();//判断org是否等于obj
void swap(int i,int j);//交换i和j列
int main()
{
int col[MAX];
int c;
int i,j;
scanf("%d",&m);
scanf("%d",&n);
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&org[i][j]);
}
}
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&obj[i][j]);
}
}
c=0;
for(i=0;i<m;i++)
{
is_row_equal(i);
}
for(j=0;j<n;j++)
{
if(!is_col_equal(j))
{
col[c++]=j;
}
}
c--;
for(i=0;i<=c;i++)
{
for(j=i+1;j<=c;j++)
{
if(col[i]!=-1 && col[j]!=-1 && (equal2(col[i],col[j]) || equal2(col[j],col[i])))
{
swap(col[i],col[j]);//交换i和j列
need++;
if(is_col_equal(i))
col[i]=-1;
if(is_col_equal(j))
col[j]=-1;
}
}
}
for(i=0;i<m;i++)
{
is_row_equal(i);
}
if(equal_all())
printf("%d",need);
else
printf("-1");
}
int is_col_equal(int i)//判断org和obj的第j列是否一致
{
int k;
for(k=0;k<m;k++)
if(org[k][i]!=obj[k][i])
break;
if(k<m)
return 0;
else
return 1;
}
int is_row_equal(int i)//判断org和obj的第i行是否一致,当不一致时,判断将org的i行翻转后是否一致,如果一致,将其翻转
{
int k;
for(k=0;k<n;k++)
if(org[i][k]!=obj[i][k])
break;
if(k<n)
{
for(k=0;k<n;k++)
if(org[i][k]^1!=obj[i][k])
break;
if(k<n)
return 0;
else
{
need++;
for(k=0;k<n;k++)
org[i][k]=org[i][k]^1;
return 1;
}
}
else
return 1;
}
int equal2(int i,int j)//判断org的i列和obj的j列是否一致
{
int k;
for(k=0;k<m;k++)
if(org[k][i]!=obj[k][j])
break;
if(k<m)
return 0;
else
return 1;
}
int equal_all()//判断org是否等于obj
{
int i,j;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
if(org[i][j]!=obj[i][j])
{
return 0;
}
return 1;
}
void swap(int i,int j)//交换i和j列
{
int k,temp;
for(k=0;k<m;k++)
{
temp=org[k][i];
org[k][i]=org[k][j];
org[k][j]=temp;
}
}