poj 2893 M × N Puzzle(八数码可行解)树状数组求解

来源:互联网 发布:淘宝假面骑士铠武腰带 编辑:程序博客网 时间:2024/06/05 08:14
某状态的奇偶性定义为逆序对(不包括0的)总数的奇偶性。

此题目终态为偶数

首先,0的左右移动不改变奇偶性。

N为奇数,上下移动不改变奇偶性,故逆序数为偶的YES

N为偶数,上下移动逆序数变化为±1,此时还要考虑0的竖直距离,逆序数%2 == 距离%2 时YES
/*********************************************** * Author: fisty * Created Time: 2015/1/31 16:15:51 * File Name   : poj2893.cpp *********************************************** */#include <iostream>#include <cstring>#include <deque>#include <cmath>#include <queue>#include <stack>#include <list>#include <map>#include <set>#include <string>#include <vector>#include <cstdio>#include <bitset>#include <algorithm>using namespace std;#define Debug(x) cout << #x << " " << x <<endl#define MAX_N 1000010const int INF = 0x3f3f3f3f;typedef long long LL;typedef pair<int, int> P;int a[MAX_N];int bit[MAX_N];int m,n,k;void add(int i, int x){    while(i <= k){        bit[i] += x;        i += i & (-i);    }}int sum(int i){    int sum = 0;    while(i > 0){        sum += bit[i];        i -= i & (-i);     }    return sum;}int solve(){    int ans = 0;    for(int i = 0;i < k; i++){       add(a[i], 1);       ans += i + 1 - sum(a[i]);    }    return ans;}int main() {    //freopen("in.txt", "r", stdin);    cin.tie(0);    ios::sync_with_stdio(false);    int n, m;       while(cin >> m >> n){        int step = 0;        k = 0;        if(!n && !m) break;        memset(bit, 0, sizeof(bit));        //memset(a, 0, sizeof(a));        for(int i = 0;i < m; i++){            for(int j = 0;j < n; j++){                int s;                cin >> s;                if(s == 0){                    step = m - i - 1;                }else{                    a[k++] = s;                }            }        }        int ans = solve();        if(n & 1)            step = 0;        if(step % 2 == ans % 2)            cout << "YES" << endl;        else             cout << "NO" << endl;    }    return 0;}



0 0
原创粉丝点击