【奇数码问题】
连接:https://ac.nowcoder.com/acm/contest/1001/F
来源:牛客网c++
你必定玩过八数码游戏,它其实是在一个33的网格中进行的,1个空格和1~8这8个数字刚好不重不漏地分布在这33的网格中。
例如:
5 2 8
1 3 _
4 6 7
在游戏过程当中,能够把空格与其上、下、左、右四个方向之一的数字交换(若是存在)。
例如在上例中,空格可与左、上、下面的数字交换,分别变成:
5 2 8 5 2 _ 5 2 8
1 _ 3 1 3 8 1 3 7
4 6 7 4 6 7 4 6 _web
奇数码游戏是它的一个扩展,在一个n\times nn×n的网格中进行,其中n为奇数,1个空格和1\sim n\times n-11∼n×n−1这n\times n-1n×n−1个数刚好不重不漏地分布在n*n的网格中。
空格移动的规则与八数码游戏相同,实际上,八数码就是一个n=3的奇数码游戏。
如今给定两个奇数码游戏的局面,请判断是否存在一种移动空格的方式,使得其中一个局面能够变化到另外一个局面。
【代码】数组
#include<bits/stdc++.h> using namespace std; vector <int> a[2]; int c[500500]; int ans; void merge(vector <int> &a,int l,int mid,int r) //运用vector的数据结构 { int i=l,j=mid+1; //定义i,j for(int k=l;k<=r;k++){ if(j>r||i<=mid&&a[i]<=a[j]) c[k]=a[i++]; //若是j<r或i<mid而且a[i]小于等于a[j],将a[i]数组复制到数组c[k]中 else c[k]=a[j++],ans+=mid-i+1; } for(int k=l;k<=r;k++) a[k]=c[k]; //将c[k]复制到a[k]中 } void guibing(vector <int> &a,int l,int r) { if(l>=r) return; //若是l大于r,函数输入错误 int mid=(l+r)>>1; guibing(a,l,mid); guibing(a,mid+1,r); merge(a,l,mid,r); //调用merge()函数// } int cal(int k) { ans=0; guibing(a[k],0,a[k].size()-1); //调用guibing()函数 return ans; } int main() { int n; while(cin>>n){ a[0].clear(); //清空数据 a[1].clear(); for(int i=1,u;i<=n*n;i++){ cin>>u; if(u) a[0].push_back(u); //尾部加入一个数据 } for(int i=1,u;i<=n*n;i++){ cin>>u; if(u) a[1].push_back(u); } puts(a[0].size()&&(cal(1) - cal(0) & 1) ? "NIE" : "TAK"); //判断输出“NIE”或“TAK” //cout<<"ans="<<cal(0)<<endl; //经过对函数cal()的调用实现对前面两个子函数的调用,输出答案 } return 0; }