絕境求生(八數碼有解無解的問題,求逆序)
問題 E: 【排序】絕境求生
時間限制: 1 Sec 記憶體限制: 64 MB
提交: 19 解決: 12
題目描述
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:
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:
The following steps solve the puzzle given above.
Given an M × N puzzle, you are to determine whether it can be solved.
樣例輸入
複製樣例資料
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
樣例輸出
YES NO
結論:N*M矩陣中,若M為奇數->計算給出矩陣的逆序數和與初始狀態的逆序數看奇偶性:奇偶相同則存在,反之不存在
若M為偶數->計算給出矩陣的逆序數為ans1,初始0所在行與給出的0所在行之間的行間距ans2,判斷:
(ans1%2) ==(ans2%2),成立則存在,反之不存在
用樹狀陣列維護
/**/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
typedef long long LL;
using namespace std;
int n, m;
int cnt;
int c[1000005], a[1000005];
int ans;
int lowbit(int x){
return x & (-x);
}
void add(int x){
while(x <= cnt){
c[x]++;
x += lowbit(x);
}
}
int sum(int x){
int su = 0;
while(x){
su += c[x];
x -= lowbit(x);
}
return su;
}
int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
while(scanf("%d %d", &n, &m) == 2){
if(!n && !m) break;
memset(c, 0, sizeof(c));
int p, x, ans = 0;
cnt = 0;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
scanf("%d", &x);
if(x == 0) p = n - i;
else{
a[cnt++] = x;
}
}
}
for (int i = cnt - 1; i >= 0; i--){
ans += sum(a[i]);
//cout << a[i] << " " <<sum(a[i]) << endl;
add(a[i]);
}
if(m & 1){
if(ans % 2 == 0){
printf("YES\n");
}else{
printf("NO\n");
}
continue;
}
if(ans % 2 == p % 2){
printf("YES\n");
}else{
printf("NO\n");
}
}
return 0;
}
/**/