题目链接:http://codeforces.com/contest/996/problem/C
一道很麻烦的模拟题。
中间两排是车辆,外面两排是停车场,停车场属于指定车辆,只有对应车辆才能进入,对应为0的停车场任何车辆都无法进入,车辆可以开到中间两排的空地,题目要求求出使所有车辆开到指定停车场的方法。
很显然,只要存在任意一个空地,所有车辆都能开进停车场。
所以判断是否存在空地就能判断是否有解,但模拟的过程是很令人头疼,当你利用一块空地时,总共要走5步才能使目标车辆向目标方向移动1步,最坏情况下,一辆车要移动5*50步才能到达目标地点,100辆车则会有25000步,这就超过了题目的步数限制。
假如把这两排抽象成一个圆形,使其旋转直到复原,就会出现每一辆车与每一个停车位都对应的情况,转圈要100*100步,满足要求。
每次把圆转动一个单位,就检查一次是否有车可以进入停车场,时间复杂度为100*100。
为了便于操作,找出任意一块空地,每对其进行2*n次操作就会回到原点。
但这样做会出错,以下给出图解为什么会错:
我们看到第一个和倒数第二个,可以认为圆旋转了90度,这是没有错的,但是我们是以空地回到原点为标准,所以转动完后,是从第一个到了最后一个,所以会漏掉1在左上角的情况。
所以每把圆转动一个单位,就检查两次(在转到一半的时候一次,结束时一次)是否有车可以进入停车场,时间复杂度为100*100*2。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<stack> #include<map> #include<vector> #include<queue> #include<set> #include<iomanip> #include<cctype> using namespace std; const int MAXN=1e5+5; const int INF=1<<30; const long long mod=1e9+7; const double eps=1e-8; #define ll long long #define edl putchar(' ') #define sscc ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define FOR(i,a,b) for(int i=a;i<=b;i++) #define ROF(i,a,b) for(int i=a;i>=b;i--) #define FORLL(i,a,b) for(ll i=a;i<=b;i++) #define ROFLL(i,a,b) for(ll i=a;i>=b;i--) #define mst(a) memset(a,0,sizeof(a)) #define mstn(a,n) memset(a,n,sizeof(a)) #define zero(x)(((x)>0?(x):-(x))<eps) struct num { int a,x,y; }; ll n,k,a[55][7]; queue<num> q; void swap(int x1,int y1,int x2,int y2) { //cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl; if(a[x1][y1]==0&&a[x2][y2]==0) return ; if(a[x1][y1]==0) swap(x1,x2),swap(y1,y2); num t; t.a=a[x1][y1],t.x=x2,t.y=y2; q.push(t); a[x1][y1]=a[x2][y2]; a[x2][y2]=t.a; } void judg(int i) { if(a[i][2]!=0&&a[i][2]==a[i][1]) { num t; t.a=a[i][2]; a[i][2]=0; t.x=i,t.y=1; q.push(t); } if(a[i][3]!=0&&a[i][3]==a[i][4]) { num t; t.a=a[i][3]; a[i][3]=0; t.x=i,t.y=4; q.push(t); } } int main() { cin>>n>>k; FOR(j,1,4) FOR(i,1,n) cin>>a[i][j]; { FOR(i,1,n) { judg(i); } if(n*2==k&&q.empty()) { cout<<-1<<endl; return 0; } } int mx=0,my,tol=2*n; FOR(J,2,3) if(mx==0) FOR(I,1,n) { if(a[I][J]==0) { mx=I,my=J; break; } } if(my==3) swap(mx,3,mx,2),my=2; while(tol--) { FOR(i,mx+1,n) swap(mx++,my,i,my); swap(mx,my++,mx,my); ROF(i,n-1,1) swap(mx--,my,i,my); FOR(i,1,n) { judg(i); } swap(mx,my--,mx,my); FOR(i,2,mx) swap(mx++,my,i,my); /*cout<<endl; FOR(i,2,3) cout<<a[1][i]<<" "<<a[2][i]<<endl; cout<<endl;*/ FOR(i,1,n) { judg(i); } } cout<<q.size()<<endl; while(!q.empty()) { num t=q.front(); q.pop(); cout<<t.a<<" "<<t.y<<" "<<t.x<<endl; } }