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 |
|
DOWN |
|
LEFT ⇒ |
|
UP |
|
… |
||||||||||||||||||||||||||||||||||||||||||||||||
RIGHT |
|
UP |
|
UP ⇒ |
|
LEFT |
|
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
Source
规律题,正好之前证过规律大概就是整个局面的逆序数+起始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; }