Time Limit: 4000MS | Memory Limit: 131072K | |
Total Submissions: 4206 | Accepted: 1163 |
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 aM 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
题意:给一个n*m的类似八数码的矩阵,编号为1~n*m-1,n*m转换为1,求能否从初始状态转移到给定状态。
思路:这边需要关于八数码推广的相关知识。
八数码问题的有解无解的结论:
一个状态表示成一维的形式,求出除0之外所有数字的逆序数之和,也就是每个数字前面比它大的数字的个数的和,称为这个状态的逆序。
若两个状态的逆序奇偶性相同,则可相互到达,否则不可相互到达。
由于原始状态的逆序为0(偶数),则逆序为偶数的状态有解。
也就是说,逆序的奇偶将所有的状态分为了两个等价类,同一个等价类中的状态都可相互到达。
简要说明一下:当左右移动空格时,逆序不变。当上下移动空格时,相当于将一个数字向前(或向后)移动两格,跳过的这两个数字要么都比它大(小),逆序可能±2;要么一个较大一个较小,逆序不变。所以可得结论:只要是相互可达的两个状态,它们的逆序奇偶性相同。我想半天只能说明这个结论的必要性,详细的证明请参考后面的附件。
N×N的棋盘,N为奇数时,与八数码问题相同。
N为偶数时,空格每上下移动一次,奇偶性改变。称空格位置所在的行到目标空格所在的行步数为空格的距离(不计左右距离),若两个状态的可相互到达,则有,两个状态的逆序奇偶性相同且空格距离为偶数,或者,逆序奇偶性不同且空格距离为奇数数。否则不能。
也就是说,当此表达式成立时,两个状态可相互到达:(状态1奇偶性==状态2奇偶性)==(空格距离%2==0)。
引自: http://blog.csdn.net/tiaotiaoyly/article/details/2008233对于这题,如果列数为奇数,那么就看逆序和是否为偶数,否则需要判断逆序和的奇偶与0的初始与给定状态的行号的差值的奇偶是否相同。
万万没想到因为初始化而一直tle。。这题有毒。
#include
#include
#include
using namespace std;
int n,m;
int cnt;
int lay[1000010];
int c[1000010];
void update(int i, int x)//i点增量为x ,更新树状数组
{
while(i <= cnt)
{
c[i] += x;
i += i&(-i);
}
}
int sum(int x)//区间求和 [1,x]
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=x&(-x);
}
return sum;
}
int solve()
{
int ans=0;
for(int i=0;i
Your are to write a program to determine whether it is possible to solve the puzzle or not.
Input
The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. The first line of each case contains only one integer M, 1 <= M <= 100. It is the size of 3D puzzle cube. Then follow M lines, each contains exactly M^2 numbers on the tiles for one layer. First is the layer on the top of the cube and the last one on the bottom. In each layer numbers are arranged from the left top corner linewise to the right bottom corner of the layer. In other words, slot with coordinates (x,y,z) is described by the (x+M.y+1)-th number on the (z+1)-th line. Numbers are separated by space. Number 0 means free position.
Output
For each case, print exactly one line. If the original configuration can be reached by sliding the tiles, print the sentence 'Puzzle can be solved.'. Otherwise, print the sentence 'Puzzle is unsolvable.'.
Sample Input
2
2
1 2 3 4
5 7 6 0
2
2 1 3 5
4 6 0 7
Sample Output
Puzzle is unsolvable.
Puzzle can be solved.
三维状况m^3的八数码扩展问题。
同上一题结论一样,只是从行距变成了两个维度上的距离之和。
#include
#include
#include
using namespace std;
int m;
int cnt;
int lay[1000010];
int c[1000010];
void update(int i, int x)//i点增量为x ,更新树状数组
{
while(i <= cnt)
{
c[i] += x;
i += i&(-i);
}
}
int sum(int x)//区间求和 [1,x]
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=x&(-x);
}
return sum;
}
int solve()
{
int ans=0;
for(int i=0;i