CF995A 特斯拉

1 CF995A 特斯拉

2 题目描述

时间限制 \(3s\) | 空间限制 \(256M\)

\(Allen\) 梦想拥有一大批电动汽车,当他准备安排他车辆的时候发现了一个问题。\(Allen\) 的停车场是一个 \(4\)\(n (n≤50)\) 列的矩形空间,每个小空间最多只能放一辆车。他幻想自己有 \(k(𝑘≤2𝑛)\) 辆车停放在里面,所有的车开始的时候都放在第二和第三行。每辆车都在第一行或者第四行有固定车位。\(Allen\) 必须把他的车放到相应的车位上去。然而因为 \(Allen\) 从不把他的车借给别人,所以只能他自己一次移动一辆车,他可以把车从任意四个正方向移动到旁边的空车位上。而且 \(Allen\) 只能移动一辆车去第一或者第四排的固定车位上。\(Allen\) 知道他会非常忙,在他意识到自己不值得浪费时间在挪车之前他最多能挪车 \(20000\) 次。帮助 \(Allen\) 找出挪车方案,如果没有方案那么建议 \(Allen\) 雇人挪车。

数据范围:\(1≤𝑛≤50, 1≤𝑘≤2𝑛\), \(n\) 是列数,\(k\) 是车的数量。

3 题解

首先,如果某些车一开始就在对应位置旁边,那么我们可以将这些车直接移动到对应位置。在移动完所有初始的车后,如果仍然剩下一些车,我们就要考虑如何移动这些车了。

如果我们让所有的车顺时针在 \(2\)\(3\) 行移动,那么在转了一圈后,每辆车都会经过所有 \(1\)\(4\) 行的对应位置旁边。这样一来,我们就可以在过程中判断,如果在转了一圈后,某辆车旁边就是其对应位置,直接将其停入即可。这样的最大总操作次数是 \((2n+1)k\),由于 \(n \le 50, k \le 100\),所以理论上限为 \(10100\) 次,小于题目要求的 \(20000\) 次,因此只要移动完初始的车后存在空位,我们就一定能找到一种合法的移动方案。

这里我们由于需要输出总步数,可以先用一个队列存储所有的移动,在最后所有车归位后再输出方案。剩余部分模拟即可。

4 代码(空格警告):

#include <iostream>
#include <queue>
using namespace std;
const int N = 55;
int n, k, st, x, y, cnt;
int Map[5][N], order[N];
bool f[N*2];
bool flag;
pair<int, int> pos[N*2];
queue< pair<int, pair<int, int> > >q;
int dir[2][2] = {{0, -1}, {0, 1}};
int main()
{
    cin >> n >> k;
    for (int i = 1; i <= 4; i++) for (int j = 1; j <= n; j++) cin >> Map[i][j];
    for (int i = 1; i <= n; i++)
    {
        if (Map[2][i] == Map[1][i] && Map[2][i])
        {
            f[Map[2][i]] = 1;
            q.push(make_pair(Map[2][i], make_pair(1, i)));
            Map[2][i] = 0;
        }
        if (Map[3][i] == Map[4][i] && Map[3][i])
        {
            f[Map[3][i]] = 1;
            q.push(make_pair(Map[3][i], make_pair(4, i)));
            Map[3][i] = 0;
        }
    }
    for (int i = 1; i <= k; i++) if (!f[i]) flag = 1;
    if (!flag)
    {
        cout << q.size() << '\n';
        while (q.size())
        {
            cout << q.front().first << " " << q.front().second.first << " " << q.front().second.second << '\n';
            q.pop();
        }
        return 0;
    }
    flag = 0;
    for (int i = 2; i <= 3; i++) for (int j = 1; j <= n; j++) if (!Map[i][j]) flag = 1;
    if (!flag) cout << -1;
    else
    {
        for (int i = 2; i <= 3; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (Map[i][j])
                {
                    pos[Map[i][j]].first = i;
                    pos[Map[i][j]].second = j;
                }
            }
        }
        for (int i = 1; i <= k; i++)
        {
            if (f[i]) continue;
            if (pos[i].first == 2)
            {
                if (!Map[pos[i].first][pos[i].second+1] && pos[i].second+1 <= n)
                {
                    st = i;
                    break;
                }
                if (pos[i].second == n && !Map[pos[i].first+1][pos[i].second])
                {
                    st = i;
                    break;
                }
            }
            else
            {
                if (!Map[pos[i].first][pos[i].second-1] && pos[i].second-1 >= 1)
                {
                    st = i;
                    break;
                }
                if (pos[i].second == 1 && !Map[pos[i].first-1][pos[i].second])
                {
                    st = i;
                    break;
                }
            }
        }
        x = pos[st].first;
        y = pos[st].second;
        order[++cnt] = st;
        for (int i = 1; i < 2 * n; i++)
        {
            if (x == 2 && y == 1) x++;
            else if (x == 3 && y == n) x--;
            else
            {
                if (x == 2)
                {
                    x += dir[0][0];
                    y += dir[0][1];
                }
                else if (x == 3)
                {
                    x += dir[1][0];
                    y += dir[1][1];
                }
            }
            if (Map[x][y]) order[++cnt] = Map[x][y];
        }
        for (int i = 1; i <= 2 * n; i++)
        {
            for (int j = 1; j <= cnt; j++)
            {
                if (f[order[j]]) continue;
                x = pos[order[j]].first;
                y = pos[order[j]].second;
                Map[x][y] = 0;
                if (x == 2 && y == n) x++;
                else if (x == 3 && y == 1) x--;
                else
                {
                    if (x == 2)
                    {
                        x += dir[1][0];
                        y += dir[1][1];
                    }
                    else if (x == 3)
                    {
                        x += dir[0][0];
                        y += dir[0][1];
                    }
                }
                Map[x][y] = order[j];
                pos[order[j]].first = x;
                pos[order[j]].second = y;
                q.push(make_pair(order[j], make_pair(x, y)));
            }
            for (int j = 1; j <= n; j++)
            {
                if (Map[2][j] == Map[1][j] && Map[2][j])
                {
                    f[Map[2][j]] = 1;
                    q.push(make_pair(Map[2][j], make_pair(1, j)));
                    Map[2][j] = 0;
                }
                if (Map[3][j] == Map[4][j] && Map[3][j])
                {
                    f[Map[3][j]] = 1;
                    q.push(make_pair(Map[3][j], make_pair(4, j)));
                    Map[3][j] = 0;
                }
            }
        }
        cout << q.size() << '\n';
        while (q.size())
        {
            cout << q.front().first << " " << q.front().second.first << " " << q.front().second.second << '\n';
            q.pop();
        }
    }
    return 0;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-03-26 00:18  David24  阅读(35)  评论(0编辑  收藏  举报