poj2893 M × N Puzzle

M × N Puzzle
Time Limit: 4000MS   Memory Limit: 131072K
Total Submissions: 3332   Accepted: 940

Description

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:

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

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:

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

The following steps solve the puzzle given above.

START

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

DOWN

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

UP

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

 

RIGHT

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

UP

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

LEFT

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

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 ≤ MN ≤ 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

Source

POJ Monthly--2006.07.30, newton88518



规律题,正好之前证过规律大概就是整个局面的逆序数+起始0的位置的坐标(x,y)中xy的和+rol+col+rol*col-1的奇偶

稍微证一下,

如果左右移动,那么起始的0的位置和终止0的位置四个坐标值相加一定是奇数,然后移动了逆序数肯定也奇偶变化,所以移动后奇偶值不变

上下移动,0的位置照样和是奇数,然后,取中间一段(0,a,b,c,d,e)变成(e,a,b,c,d,0),那么如果列为奇数,那么0往前移动关于0的逆序对奇偶不变,关于e的奇偶也不变,如果列为偶数,两个都变化总奇偶也不变。

所以,只要保证奇偶不变就能走到,奇偶变了就走不到了

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define MAXN 1000005

struct Tree
{
    int l,r,val;
};

Tree tree[MAXN*5];
int n;

void Build(int t,int l,int r)
{
    tree[t].val=0;
    tree[t].l=l;
    tree[t].r=r;
    if (l==r) return;
    int mid=(l+r)/2;
    Build(2*t+1,l,mid);
    Build(2*t+2,mid+1,r);
}

int Count(int t,int l,int r)
{
    if (tree[t].l==l && tree[t].r==r) return tree[t].val;
    int ret=0;
    int mid=(tree[t].l+tree[t].r)/2;
    if (l<=mid) ret+=Count(2*t+1,l,min(r,mid));
    if (r>mid) ret+=Count(2*t+2,max(l,mid+1),r);
    return ret;
}

void Update(int t,int idx)
{
    int l=tree[t].l;
    int r=tree[t].r;
    if (l==r)
    {
        tree[t].val=1;
        return;
    }
    int mid=(l+r)/2;
    if (idx<=mid) Update(2*t+1,idx);
    else Update(2*t+2,idx);
    tree[t].val=tree[2*t+1].val+tree[2*t+2].val;
}

int main()
{
    int i,j,r,c,x;
    while(1)
    {
        scanf("%d%d",&r,&c);
        if (r==0 && c==0) break;
        n=r*c;
        Build(0,0,n-1);
        long long sum=r+c+n-1;
        for (i=0;i<r;i++)
        {
            for (j=0;j<c;j++)
            {
                scanf("%d",&x);
                if (x==0)
                {
                    sum+=(i+j);
                }
                sum+=Count(0,x,n-1);
              //  printf("%d: %lld\n",x,Count(0,x,n-1));
                Update(0,x);
            }
        }
        if (sum%2==0) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


你可能感兴趣的:(poj2893 M × N Puzzle)