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