Codeforces Round #492 (Div. 2) C. Tesla

链接

http://codeforces.com/contest/996/problem/C

题解

英语不好,一开始理解错了题意,写了个 3 K 的代码结果不停地 W A ,后来我才知道一种车库只能让对应的汽车进去。
正解是这样的,你让汽车不停的打转转,如果谁到了自家门口就进去。
无解的条件就是一开始没有空位而且没有任何一辆汽车在自家门前。
这里有个地方很难调试,就是旋转的时候,如果你总是机械的使用每次都相同的 f o r 循环,那么很可能使得每次 0 都回到相同的位置,我觉得可以写一段代码,每次寻找 0 的位置,然后让它不停的和相邻的汽车交换位置(沿着固定的方向),且每次 0 停止的位置都和上次不一样。
想一下,如果 0 每次都回到相同的位置,那么这个 0 就相当于占有了这个位置,如果一辆车必须从这个位置进入车库,那就陷入死循环了。
我最后使用了随机化,每次移动都有 50 % 的概率取消,从而保证不会被极端数据卡掉。
以上是基于先让所有的汽车都转一圈再检查能不能进车库的算法,如果你使用每次移动汽车都检查它有没有来到自家门前,则不需要考虑上述问题

代码

#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;
}

猜你喜欢

转载自blog.csdn.net/fsahfgsadhsakndas/article/details/80963602