拼图游戏(C语言)

文章讨论了一个关于N*N数字矩阵的拼图游戏问题,其中0代表空格。通过计算逆序数和考虑0所在位置的行号与列号的奇偶性,判断是否能通过无限次交换达到目标矩阵。算法基于线性代数的逆序数定理,限制条件为2<N≤4。

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

sustoj

Description

拼图游戏即任意一个N*N(N>1)的拼图中,会把一张完整的图片裁切成N*N块,去掉尾部一块,然后打乱顺序,通过调换空格块与邻块的位置来还原图片。为了方便计算,我们规定右下角最后一块图片为空,用0代替,其余每一块图片用从1~N*N-1的数字来表示。我们简单示范一下数字拼图的操作吧。

例如3*3的拼图

142

835

670

可以通过0与其他数字横竖交换得到新的拼图

142

830

675

中间可进行无限次0与其他数字的交换。我们最终需要将整张图还原为

123

456

780

我们需要做的就是计算数字拼图还原。是计算还原所需最小的步数吗?当然不是,那对于现在的你们来说还有点困难。我们就从简单的开始吧。首先为了简化操作可以将规定2<=N<=4。

问:任意给一个N*N数字矩阵,能否证明:经过无限次的交换,一定能到达目标矩阵或者经过无限的交换也不能实现目标矩阵?如果能输出YES,如果不能输出NO。

Input Format

第一行输出N,接下来为(0~N*N-1)的数字矩阵。同行数字间保证有一空格。我们保证一开始0在右下角,且数字符合要求。N为0结束。

Output Format

如果能还原输出YES,如果不能还原输出NO。

思路:线性代数逆序数定理

#include <stdio.h>

int main()
{	
	int i, j, k = 0, K, sum, n;
	int x, y;
	int a[100][100], b[10000];//a用于求解 0 的行号列号,b 用于求解逆序数 
	
	while(scanf("%d", &n) && n)
	{
		sum = 0; k = 0;// 运用到++或--的变量,在循环时要初始化 
		for(i = 0; i < n; i++)
		{
			for(j = 0; j < n; j++)
			{
				scanf("%d", &a[i][j]);
				if(a[i][j] == 0)
				{
					x = i; y = j;
				}
				b[k++] = a[i][j];
			}
		}
		
		K = k;
		//图形逆序数计算 
		for(i = 0; i <= K - 1; i++)
		{
			for(j = i + 1; j <= K - 1; j++)
			{
				if(b[i] > b[j])
				{
					sum++;
				}
			}
		}
		//利用图形A与图形B等价的充要条件图形A的排列的逆序数加上0元素行号和列号的奇偶性等于图形B的排列的逆序数加上0元素行号和列号的奇偶性定理 
		sum += (x + y);
		 
		if(((sum % 2 == 0) && ((n * n - 1) % 2 == 0)) || 
			((sum % 2 != 0) && ((n * n - 1) % 2 != 0)))
		{
			printf("YES\n");
		}
		else
		{
			printf("NO\n");
		}
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值