1. 程式人生 > >【練習——逆序對】N*M Puzzle / Simple Puzzle

【練習——逆序對】N*M Puzzle / Simple Puzzle

HDU P3600 Simple Puzzle 

POJ P2893 N*M Puzzle

(咕在前面, 這是兩道基本一樣的題, 我都沒有A掉, 但我覺得我寫的十分正確!!!不想改了先放上來orz

思路:這個題真是妙啊qwq我特意新建了一個“妙啊”分類給它qwq(然而A不掉

  • 將二維轉化為一維, 從左往右從上至下, 遇到0(空格)跳之~
  • 可知空格左右移動對一維序列無影響, 上下移動會向前或向後移動, 跳過(m-1)個格子//這裡n行m列 
  • 如果列數為奇數, (m-1)為偶數, 則無論移動的數與跳過的數的大小關係如何, 逆序對數奇偶性不變;
  • 也就是說具有同奇偶性的逆序對數的數列是可以互相轉化的, 初始數列逆序對數為0, 只要逆序對數為偶數, 即可輸出“YES”
  • 如果列數為偶數, (m-1)為奇數, 則無論移動的數與跳過的數的大小關係如何, 逆序對數奇偶性一定改變;
  • 同理, 空格移動行數若為奇數, 逆序對數奇偶性發生改變
  • (太亂了!!!!貼個講的清楚地QAQ 

貼上我可憐的無助的至今在兩大oj還是wa的程式碼!(輸入格式附和POJ

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 const int sz = 1000;
 6 int n, m, flag, num = 0
, cnt = 0, x, a[sz*sz], b[sz*sz]; 7 void merge_sort(int l, int r) { 8 if(r - l > 0) { 9 int mid = (l + r) >> 1; 10 int i = l, p = l, q = mid + 1; 11 merge_sort(l, mid); 12 merge_sort(mid+1, r); 13 while(q <= r|| p <= mid) { 14 if
(q > r || (p <= mid && a[p] <= a[q])) 15 b[i++] = a[p++]; 16 else b[i++] = a[q++], cnt = cnt + mid - p + 1; 17 } 18 for(int i = l; i <= r; i++) 19 a[i] = b[i]; 20 } 21 } 22 int main() { 23 while(1) { 24 scanf("%d%d", &n, &m); 25 if(n==0&&m==0) break; 26 num = 0; 27 memset(a, 0, sizeof(a)); 28 memset(b, 0, sizeof(b)); 29 for(int i = 1; i <= n; i++) { 30 for(int j = 1; j <= m; j++) { 31 scanf("%d", &x); 32 if(x==0) { 33 flag = i; 34 continue; 35 } 36 a[++num] = x; 37 } 38 } 39 cnt = 0; 40 merge_sort(1, num); 41 if(m%2==1) { 42 if(cnt%2==1) { 43 if((n-flag)%2==1) printf("YES\n"); 44 else printf("NO\n"); 45 } 46 else { 47 if((n-flag)%2==1) printf("NO\n"); 48 else printf("YES\n"); 49 } 50 } 51 else { 52 if(cnt%2 == 0) printf("YES\n"); 53 else printf("No\n"); 54 } 55 } 56 return 0; 57 }