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 }