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
#include
#include
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