news 2026/9/5 13:34:43

P10454 奇数码问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
P10454 奇数码问题

P10454 奇数码问题

题目描述

你一定玩过八数码游戏,它实际上是在一个3×33 \times 33×3的网格中进行的,111个空格和1∼81 \sim 818888个数字恰好不重不漏地分布在这3×33 \times 33×3的网格中。

例如:

5 2 8 1 3 _ 4 6 7

在游戏过程中,可以把空格与其上、下、左、右四个方向之一的数字交换(如果存在)。

例如在上例中,空格可与左、上、下面的数字交换,分别变成:

5 2 8 5 2 _ 5 2 8 1 _ 3 1 3 8 1 3 7 4 6 7 4 6 7 4 6 _

奇数码游戏是它的一个扩展,在一个n×nn \times nn×n的网格中进行,其中nnn为奇数,111个空格和1∼n2−11 \sim n^2-11n21n2−1n^2-1n21个数恰好不重不漏地分布在n×nn \times nn×n的网格中。

空格移动的规则与八数码游戏相同,实际上,八数码就是一个n=3n=3n=3的奇数码游戏。

现在给定两个奇数码游戏的局面,请判断是否存在一种移动空格的方式,使得其中一个局面可以变化到另一个局面。

输入格式

多组数据,对于每组数据:

111行输入一个整数nnnnnn为奇数。

接下来nnn行每行nnn个整数,表示第一个局面。

再接下来nnn行每行nnn个整数,表示第二个局面。

局面中每个整数都是0∼n2−10 \sim n^2-10n21之一,其中用000代表空格,其余数值与奇数码游戏中的意义相同,保证这些整数的分布不重不漏。

输出格式

对于每组数据,若两个局面可达,输出TAK,否则输出NIE

输入输出样例 #1

输入 #1

3 1 2 3 0 4 6 7 5 8 1 2 3 4 5 6 7 8 0 1 0 0

输出 #1

TAK TAK

说明/提示

1≤n<5001 \le n < 5001n<500

奇数码问题题解

这是我针对奇数码问题的解题题解,核心依托归并排序求逆序对来完成可达性判断,下面结合我的代码详细拆解解题思路。

一、题目分析

本题要求我们判断两个n×nn \times nn×nnnn为奇数)的奇数码局面是否可达,其中000代表空格,其余数字为1∼n2−11 \sim n^2-11n21,空格仅能与上下左右相邻数字交换。这是一道经典的数码问题,核心在于掌握奇数码局面可达性的判定定理,同时需要高效求解逆序对。

二、核心解题思路

1. 奇数码可达性判定定理

对于nnn为奇数的奇数码问题,两个局面可达的充要条件是:忽略空格(数字000)后,两个局面的数字序列的逆序对数量奇偶性相同。

  • 逆序对定义:对于一个数字序列,若存在两个数aia_iaiaja_jaji<ji < ji<j),满足ai>aja_i > a_jai>aj,则称这对数字为一个逆序对。
  • 为什么该定理成立?因为空格的移动(与相邻数字交换)不会改变整个序列逆序对数量的奇偶性,因此只有当两个局面的逆序对奇偶性一致时,才可以通过移动空格实现相互转化。

2. 逆序对的高效求解

由于nnn最大接近500500500n2n^2n2最大为250000250000250000,普通的暴力枚举(O(n4)O(n^4)O(n4))会超时,因此我采用归并排序求解逆序对,时间复杂度为O(mlog⁡m)O(m \log m)O(mlogm)m=n2m = n^2m=n2),能够高效处理最大数据量。

三、代码逐部分解析

intn;inta[250005];intt[250005];longlongans,ans1,ans2;voidms(intl,intr){if(l==r)return;// 递归终止条件:区间仅含一个元素,无需排序intm=(l+r)/2;ms(l,m);// 递归处理左区间 [l, m]ms(m+1,r);// 递归处理右区间 [m+1, r]intlp=l;// 左区间指针intrp=m+1;// 右区间指针inttp=l;// 临时数组t的指针while(lp<=m&&rp<=r){if(a[rp]<a[lp]){t[tp]=a[rp];if(a[rp]!=0){// 忽略空格0,不统计0参与的逆序对ans+=m-lp+1;// 核心:统计逆序对数量}tp++;rp++;}else{t[tp]=a[lp];tp++;lp++;}}// 处理左区间剩余元素while(lp<=m){t[tp]=a[lp];tp++;lp++;}// 处理右区间剩余元素while(rp<=r){t[tp]=a[rp];tp++;rp++;}// 将临时数组的有序元素复制回原数组afor(inti=l;i<=r;i++){a[i]=t[i];}return;}longlongcalc(intx){for(inti=1;i<=x*x;i++){cin>>a[i];// 读取x*x个元素,将二维矩阵展平为一维数组}ans=0;// 初始化逆序对数量为0ms(1,x*x);// 调用归并排序统计逆序对returnans;// 返回当前局面的逆序对数量}intmain(){while(cin>>n){// 多组输入,直到输入结束ans1=calc(n);// 计算第一个局面的逆序对数量ans2=calc(n);// 计算第二个局面的逆序对数量if(ans1%2==ans2%2){cout<<"TAK\n";// 奇偶性相同,可达}else{cout<<"NIE\n";// 奇偶性不同,不可达}}return0;}

1. 全局变量说明

  • nnn:存储奇数码矩阵的边长,因多组输入,在循环中读取。
  • a[]a[]a[]:用于存储展平后的n×nn \times nn×n数码矩阵(二维转一维,方便归并排序处理),数组大小250005250005250005是为了容纳500×500=250000500 \times 500 = 250000500×500=250000个元素,预留充足余量。
  • t[]t[]t[]:归并排序的临时辅助数组,用于合并两个有序子数组,避免直接修改原数组导致数据混乱。
  • ansansans:临时存储单个局面的逆序对数量;ans1ans1ans1ans2ans2ans2分别存储两个输入局面的逆序对数量。

2. 归并排序求逆序对(ms 函数)

  • 函数功能:对aaa数组的[l,r][l, r][l,r]区间进行归并排序,同时统计该区间内忽略000后的逆序对数量,累加到全局变量ansansans中。
  • 核心逻辑(合并阶段统计逆序对):当a[rp]<a[lp]a[rp] < a[lp]a[rp]<a[lp]时,说明a[rp]a[rp]a[rp]与左区间中从lplplpmmm的所有元素都构成逆序对,因此逆序对数量增加m−lp+1m - lp + 1mlp+1;同时通过a[rp]!=0判断,跳过空格000,不统计其参与的逆序对,符合可达性判定定理的要求。
  • 归并排序的稳定性:保证了在统计逆序对时不会重复或遗漏,是高效求解逆序对的经典方法。

3. 读取局面并计算逆序对(calc 函数)

  • 函数功能:读取一个x×xx \times xx×x的数码局面,将其展平为一维数组后,调用归并排序函数计算逆序对数量,并返回该值。
  • 二维转一维:无需额外存储二维数组,直接按行读取所有元素存入aaa数组,简化了数据处理逻辑,同时不影响逆序对的统计结果(因为矩阵的行优先展平不改变数字之间的相对位置关系)。

4. 主函数(多组输入处理与可达性判断)

  • 多组输入处理:使用while(cin>>n)循环读取每组数据的边长nnn,适配题目多组输入的要求。
  • 可达性判断:通过比较两个局面逆序对数量的奇偶性,若相同则输出TAK(可达),否则输出NIE(不可达),完全符合奇数码可达性判定定理。

四、总结

本题的核心是掌握奇数码问题的可达性判定定理,以及使用归并排序高效求解逆序对。我的代码通过“二维矩阵展平 + 归并排序统计逆序对 + 奇偶性判断”的流程,高效且准确地解决了该问题,能够适配n<500n < 500n<500的最大数据规模。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 0:55:21

告别App Store限制:ipatool如何用5行命令解锁iOS应用自由

告别App Store限制&#xff1a;ipatool如何用5行命令解锁iOS应用自由 【免费下载链接】ipatool Command-line tool that allows searching and downloading app packages (known as ipa files) from the iOS App Store 项目地址: https://gitcode.com/GitHub_Trending/ip/ipa…

作者头像 李华
网站建设 2026/9/4 15:50:28

基于HAL库的CubeMX ADC单通道采样全面讲解

从零开始搞懂STM32 ADC单通道采样&#xff1a;CubeMX HAL实战全解析 你有没有遇到过这种情况&#xff1f;接了一个温度传感器&#xff0c;代码写完一烧录&#xff0c;串口打印出来的数值跳得像心电图&#xff1b;或者明明输入是1.65V&#xff0c;读出来却是2000多——离4095差…

作者头像 李华
网站建设 2026/9/4 2:43:35

戴森电池开源固件深度探索:5大隐藏功能完整揭秘

为什么你的戴森吸尘器会在两年后突然"死亡"&#xff1f;这并非偶然故障&#xff0c;而是原厂精心设计的"计划性报废"策略。通过开源固件&#xff0c;我们不仅能够解锁被隐藏的电池平衡功能&#xff0c;更能彻底改变产品的使用体验。 【免费下载链接】FU-Dy…

作者头像 李华
网站建设 2026/9/2 9:32:25

xdotool桌面自动化完整指南:零基础掌握Linux自动化操作

xdotool桌面自动化完整指南&#xff1a;零基础掌握Linux自动化操作 【免费下载链接】xdotool fake keyboard/mouse input, window management, and more 项目地址: https://gitcode.com/gh_mirrors/xd/xdotool xdotool是一个功能强大的Linux桌面自动化工具&#xff0c;…

作者头像 李华
网站建设 2026/9/2 11:02:41

CXPatcher实战指南:全方位提升CrossOver兼容性的终极解决方案

CXPatcher实战指南&#xff1a;全方位提升CrossOver兼容性的终极解决方案 【免费下载链接】CXPatcher A patcher to upgrade Crossover dependencies and improve compatibility 项目地址: https://gitcode.com/gh_mirrors/cx/CXPatcher 在跨平台游戏和软件兼容性领域&a…

作者头像 李华