金币阵列问题

本文介绍了一种通过特定规则变换金币阵列状态的算法。该算法的目标是从初始状态达到目标状态,并尽量减少变换次数。文章详细阐述了实现这一目标的具体步骤,包括如何通过翻转行和交换列来调整金币阵列。

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

问题描述:

有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;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值