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