hdu6620 Just an Old Puzzle

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=6620

题目描述

ou are given a 4 × 4 grid, which consists of 15 number cells and an empty cell.
All numbers are unique and ranged from 1 to 15.
In this board, the cells which are adjacent with the empty cell can move to the empty cell.
Your task is to make the input grid to the target grid shown in the figure below.
In the following example (sample input), you can get the target grid in two moves.

 

Input

The first line contains an integer T (1 <= T <= 10^5) denoting the number of test cases.
Each test case consists of four lines each containing four space-separated integers, denoting the input grid. 0 indicates the empty cell.

Output

For each test case, you have to print the answer in one line.
If you can’t get the target grid within 120 moves, then print 'No', else print 'Yes'.

输入输出样例

Sample Input

2

1 2 3 4

5 6 7 8

9 10 0 12

13 14 11 15

1 2 3 4

5 6 7 8

9 10 11 12

13 15 14 0

Sample Output

Yes

No

题意

八数码问题的变形,只不过格子是4*4的。

输入一个数字网格,让你判断可否在120步内将网格的数字移动成为目标网格。

题目理解

题目不会做,看的别人的思路。

网格有解(即将当前网格移动到目标网格)满足以下性质:

1.如果该网格有解,那么它完全可以在80步之内移动到目标网格。所以题目可以转化为判断网格是否有解。

2.若格子列数为奇数,则逆序数必须为偶数。

3.若格子列数为偶数,且逆序数为偶数,则当前空格所在行数与初始空格所在行数的差为偶数。

4.若格子列数为偶数,且逆序数为奇数,则当前空格所在行数与初始空格所在行数的差为奇数。

(逆序数即4*4网格展开后所得序列的逆序数,比如目标网格展开后的序列为1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0)

从初始网格到目标网格,都是那个空白格子不断移动的结果。空白格子左右移动不影响序列逆序数的奇偶,对于上下移动,如果格子列数为奇数,逆序数奇偶不变,如果格子列数为偶数,逆序数奇偶反转(验证一下)。而由于目标网格的逆序数为偶数,且网格列数为4,是偶数,那么我们可以将性质3、4作为依据,判断初始网络是否有解了。

疑点

事实上,我们只能说明只要有解,就一定满足性质3、4,但我们还不能说明满足性质3、4就一定有解,充要性并未得证。另外,关于性质1为何正确我也不明白。欢迎大佬留言指教,多谢!

代码

#include 
using namespace std;
int a[20];
int main(){
	int i,j,t,pos;
	cin>>t;
	while(t--){
		int ans=0;
		for(i=1;i<=16;i++){
			scanf("%d",&a[i]);
			if(a[i]==0){
				pos=i/4+(i%4!=0); //空位的行数 
			}
			else{                 //求逆序数
				for(j=1;ja[i])ans++;
				}
			}
			
		}
		if((4-pos)%2==ans%2){
			cout<<"Yes"<

 

你可能感兴趣的:(组合数学)