1 条题解
-
0
Eight Puzzle 可解性判定算法分析
题目理解
给定一个 的滑动拼图,其中:
- 至少 或 是奇数
- 包含 个编号瓦片和一个空缺位()
- 只能交换 与相邻瓦片
- 目标状态为数字按行升序排列, 在右下角
解题方法
核心思路
判断拼图是否可解基于以下数学性质:
- 逆序对奇偶性:计算除 外数字序列的逆序对数
- 零位置行数:计算 所在行从底部数的行数
- 可解条件:
- 当 为奇数时:逆序对数必须为偶数
- 当 为偶数时: 必须为偶数
算法实现
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1e6 + 10; int n,m,pos,x,ans,zero; int seq[maxn],tmp[maxn]; void msort(int l,int r) // 归并排序计算逆序对 { if(l==r) return ; int mid=(l+r)>>1; msort(l,mid); msort(mid+1,r); int i=l,j=mid+1,k=l-1; while(i<=mid&&j<=r) { if(seq[i]<=seq[j]) tmp[++k]=seq[i],i++; else tmp[++k]=seq[j],j++,ans+=mid-i+1; // 统计逆序对 } while(i<=mid) tmp[++k]=seq[i],i++; while(j<=r) tmp[++k]=seq[j],j++; for(int qwq=l;qwq<=r;qwq++) seq[qwq]=tmp[qwq]; } int main() { while(scanf("%d%d",&n,&m)==2 && m) { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&x); if(x) seq[++pos]=x; // 存储非零数字 else zero=n-i; // 计算零位置行数(从底部数) } msort(1,pos); // 计算逆序对 if(m&1) zero=0; // 当列数为奇数时忽略零位置 if((ans+zero)%2==0) printf("YES\n"); else printf("NO\n"); ans=0;pos=0;zero=0; // 重置变量 } return 0; }
- 1
信息
- ID
- 1894
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者