链接
http://codeforces.com/contest/996/problem/C
题解
英语不好,一开始理解错了题意,写了个
3K
3
K
的代码结果不停地
WA
W
A
,后来我才知道一种车库只能让对应的汽车进去。
正解是这样的,你让汽车不停的打转转,如果谁到了自家门口就进去。
无解的条件就是一开始没有空位而且没有任何一辆汽车在自家门前。
这里有个地方很难调试,就是旋转的时候,如果你总是机械的使用每次都相同的
for
f
o
r
循环,那么很可能使得每次
0
0
都回到相同的位置,我觉得可以写一段代码,每次寻找的位置,然后让它不停的和相邻的汽车交换位置(沿着固定的方向),且每次
0
0
停止的位置都和上次不一样。
想一下,如果每次都回到相同的位置,那么这个
0
0
就相当于占有了这个位置,如果一辆车必须从这个位置进入车库,那就陷入死循环了。
我最后使用了随机化,每次移动都有的概率取消,从而保证不会被极端数据卡掉。
以上是基于先让所有的汽车都转一圈再检查能不能进车库的算法,如果你使用每次移动汽车都检查它有没有来到自家门前,则不需要考虑上述问题
代码
#include <cstdio>
#include <algorithm>
#include <cstdio>
#define maxn 100
#define rep(x) for(int i=1;i<=x;i++)
#define rd (rand()&1)
using namespace std;
int now[10][maxn], dx[maxn], dy[maxn], n, k, q[200010][3], head, tail, res;
void push(int a, int b, int c)
{
q[tail][0]=a, q[tail][1]=b, q[tail][2]=c;
tail++;
}
void up(int x, int y)
{
push(now[x][y],x-1,y);
swap(now[x][y],now[x-1][y]);
}
void down(int x, int y)
{
push(now[x][y],x+1,y);
swap(now[x][y],now[x+1][y]);
}
void left(int x, int y)
{
push(now[x][y],x,y-1);
swap(now[x][y],now[x][y-1]);
}
void right(int x, int y)
{
push(now[x][y],x,y+1);
swap(now[x][y],now[x][y+1]);
}
void park()
{
int i, t;
for(i=1;i<=n;i++)
{
t=now[2][i];
if(i==dy[t] and dx[t]==1)up(2,i), res--;
}
for(i=1;i<=n;i++)
{
t=now[3][i];
if(i==dy[t] and dx[t]==4)down(3,i), res--;
}
}
void init()
{
int i, j;
scanf("%d%d",&n,&k);res=k;
for(i=1;i<=4;i++)for(j=1;j<=n;j++)scanf("%d",now[i]+j);
for(i=1;i<=4;i+=3)for(j=1;j<=n;j++)if(now[i][j])dx[now[i][j]]=i, dy[now[i][j]]=j, now[i][j]=0;
park();
}
void spin()
{
int i;
for(i=n-1;i;i--)if(now[2][i] and now[2][i+1]==0 and rd)right(2,i);
if(now[3][1] and now[2][1]==0 and rd)up(3,1);
for(i=2;i<=n;i++)if(now[3][i] and now[3][i-1]==0 and rd)left(3,i);
if(now[2][n] and now[3][n]==0 and rd)down(2,n);
}
void show()
{
for(printf("%d\n",tail-head);head^tail;head++)printf("%d %d %d\n",q[head][0],q[head][1],q[head][2]);
}
int main()
{
int i;
init();
for(i=1;i<=n;i++)if(now[2][i]==0 or now[3][i]==0)break;
if(i>n){printf("-1");return 0;}
while(res)spin(), park();
show();
return 0;
}