M × N Puzzle POJ - 2893

原题链接

考察: 归并排序

八数码的延伸版,这里允许了N为偶数,所以要分情况讨论

当N为偶数,向下挪一行奇偶改变,再向下挪奇偶又改变,因此答案和0的位置有关

易错:

        判断条件的时候,&1两边都要打括号不然报错

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 #define ll long long
 5 const int N = 1e6+10;
 6 int m,n;
 7 ll a[N],tmp[N];
 8 ll merge(int l,int r)
 9 {
10     if(l>=r) return 0;
11     ll mid = (ll)l+r>>1ll;
12     ll cnt = merge(l,mid) + merge(mid+1,r);
13     ll i = l; ll j = mid+1; int k = 1;//在递归过程中,a数组是从l开始排序的
14     while(i<=mid&&j<=r){
15         if(a[i]<=a[j]) tmp[k++] = a[i++];
16         else{ tmp[k++] = a[j++];cnt+=mid-i+1; }
17     }
18     while(i<=mid) tmp[k++] = a[i++];
19     while(j<=r) tmp[k++] = a[j++];
20     for(int i=l,k=1;i<=r;i++,k++) a[i] = tmp[k];//k不能从l开始,因为是从1开始赋值
21     return cnt;
22 }
23 int main()
24 {
25     //freopen("in.txt","r",stdin);
26     while(scanf("%d%d",&m,&n)!=EOF&&(n!=0||m!=0))
27     {
28         ll step;
29         for(int i=1,k=1;i<=m;i++){
30             for(int j=1;j<=n;j++){
31                 int x; scanf("%d",&x);
32                 if(x) a[k++] = x;
33                 else step = m-i;//当前行 
34             }
35         }
36         ll ans = merge(1,m*n-1);
37         if(n & 1) step = 0;
38         printf(((step&1) == (ans&1))? "YES\n" : "NO\n");
39     }
40     return 0;
41 }

 

posted @ 2021-01-06 11:24  acmloser  阅读(76)  评论(0编辑  收藏  举报