M × N Puzzle POJ - 2893(奇数码)

The Eight Puzzle, among other sliding-tile puzzles, is one of the famous problems in artificial intelligence. Along with chess, tic-tac-toe and backgammon, it has been used to study search algorithms.

The Eight Puzzle can be generalized into an M × N Puzzle where at least one of M and N is odd. The puzzle is constructed with MN − 1 sliding tiles with each a number from 1 to MN − 1 on it packed into a M by N frame with one tile missing. For example, with M = 4 and N = 3, a puzzle may look like:

162
403
759
10811

Let's call missing tile 0. The only legal operation is to exchange 0 and the tile with which it shares an edge. The goal of the puzzle is to find a sequence of legal operations that makes it look like:

123
456
789
10110

The following steps solve the puzzle given above.

START

162
403
759
10811

DOWN

102
463
759
10811
LEFT
120
463
759
10811

UP

123
460
759
10811

 

RIGHT

123
406
759
10811

UP

123
456
709
10811
UP
123
456
789
10011

LEFT

123
456
789
10110

GOAL

Given an M × N puzzle, you are to determine whether it can be solved.

Input

The input consists of multiple test cases. Each test case starts with a line containing M and N (2 M, N ≤ 999). This line is followed by M lines containing N numbers each describing an M × N puzzle.

The input ends with a pair of zeroes which should not be processed.

Output

Output one line for each test case containing a single word YES if the puzzle can be solved and NO otherwise.

Sample Input

3 3
1 0 3
4 2 5
7 8 6
4 3
1 2 5
4 6 9
11 8 10
3 7 0
0 0

Sample Output

YES
NO


题意:给你一个m*n的矩阵,0代表空,0位置可以和上下左右位置交换,问是否可以变成1~m*n-1顺序排列且0在第m*n的位置的图,看上面例子。
思路:这就是一个奇数码问题的扩展,我们将其看成一条链,将0去除。
对于n的奇数码问题,我们知道若能从一个图转换成另一张图,只需要比较两个图的逆序对奇偶性是否相同即可。(上下交换,交换n-1个数,n-1为偶数,不影响逆序对奇偶性)
对于n的偶数码问题,我们左右交换依然不增减逆序对,但是上下交换,将交换n-1个数,n-1为奇数,将改变逆序对奇偶性,我们需要判断 【一个图的逆序对+空位置行的差值】与【另一图的逆序对】
 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 using namespace std;
 5 
 6 const int maxn = 1e6+6;
 7 int a[maxn];
 8 typedef long long ll;
 9 int Mergesort(int l,int r)
10 {
11     int mid = (l+r)/2;
12     int b[r-l+5];
13     int i=l,j=mid+1;
14     int m=0;
15     int cnt = 0;
16     while(i <= mid && j <= r)
17     {
18         if(a[i] > a[j])
19             b[m++] = a[j++],cnt += mid-i+1;
20         else
21             b[m++] = a[i++];
22     }
23     while(i <= mid)
24     {
25         b[m++] = a[i++];
26     }
27     while(j <= r)
28     {
29         b[m++] = a[j++];
30     }
31     m = 0;
32     for(int i=l; i<=r; i++)
33     {
34         a[i] = b[m++];
35     }
36     return cnt;
37 }
38 
39 void Merge(int l,int r,ll& ans)
40 {
41     if(l >= r)
42         return;
43     int mid = (l+r)/2;
44     Merge(l,mid,ans);
45     Merge(mid+1,r,ans);
46     ans += Mergesort(l,r);
47 }
48 int n,m;
49 int main()
50 {
51     while(~scanf("%d%d",&n,&m)&&n&&m)
52     {
53         int tmp;
54         int cnt = 1;
55         int row;
56         for(int i=1; i<=n; i++)
57         {
58             for(int j=1; j<=m; j++)
59             {
60                 scanf("%d",&tmp);
61                 if(tmp)
62                     a[cnt++] = tmp;
63                 else row = i;
64             }
65         }
66         ll ans = 0;
67         Merge(1,cnt-1,ans);
68         int flag = 0;
69         if(m&1){if((ans & 1) == 0)flag = 1;}
70         else if((ans+n-row) % 2 == 0)flag = 1;
71         if(flag)printf("YES\n");
72         else printf("NO\n");
73     }
74 }
View Code

 



 

转载于:https://www.cnblogs.com/iwannabe/p/10168994.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值