题目链接:
https://codeforces.com/problemset/problem/1428/D
题目大意:
给定一个n*n的网格,现在从每一列的最下方向上仍一个回旋镖
网格上有一些障碍物,当回旋镖击打到障碍物时,其会按照
(上到左,左到下,下到右)顺时针方向更改飞行方向,直到出网格
现在我们设在第i列扔出去的飞镖击打到障碍物的个数为ai
给定 a1, a2, ... an 问是否能使用0 <= t <= 2*n 个障碍物使其得以满足
输入与输出:
输入:
第一行一个n代表网格大小,之后n个数代表ai(0 <= ai <= 3)
输出:
如果能满足a1到an则输出一个t代表障碍物数量
跟着t行代表每个障碍物坐标(行,列)
如果不能满足,则输出-1
思路:
因为飞镖顺时针改变方向,我们则应该从右到左来讨论
因为ai很小,我们可以分组讨论一下,
如果ai为0
则其实这一列我们可以直接忽略掉
如果ai为1
则这一列会占用一行未放置任何障碍物的行
如果ai为2
则这一列需要用一行已经放了一行障碍物的行
如果ai为3
则这一列需要一行空行,且需要某只放了一个障碍物的列
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 1e5 + 5;
int n, nums2, nums1, nums0, minNotUse;
int xx[maxn];
queue<pair<int, int>> que1, que2;
queue<pair<int, int>> resque;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &xx[i]);
bool ff = 1;
nums0 = n;
minNotUse = 1;
for (int ii = n; ii >= 1; ii--) {
if (!xx[ii]) continue;
else if (xx[ii] == 1) {
if (!nums0) {
ff = 0;
break;
}
nums0--;
nums1++;
que1.push(make_pair(ii, minNotUse));
resque.push(make_pair(ii, minNotUse));
minNotUse++;
}
else if (xx[ii] == 2) {
if (!nums1) {
ff = 0;
break;
}
nums1--;
nums2++;
int ii1 = que1.front().first;
int jj1 = que1.front().second;
que1.pop();
que2.push(make_pair(ii, jj1));
resque.push(make_pair(ii, jj1));
}
else {
if (!nums0 || (!nums1 && !nums2)) {
ff = 0;
break;
}
nums0--;
int ii1;
int jj1;
if (nums2) {
ii1 = que2.front().first;
jj1 = que2.front().second;
que2.pop();
nums2--;
}
else{
ii1 = que1.front().first;
jj1 = que1.front().second;
que1.pop();
nums1--;
}
nums2++;
que2.push(make_pair(ii, minNotUse));
resque.push(make_pair(ii, minNotUse));
resque.push(make_pair(ii1, minNotUse));
minNotUse++;
}
}
if (!ff) printf("-1\n");
else {
printf("%d\n", resque.size());
while (resque.size()) {
printf("%d %d\n", n - resque.front().second + 1, resque.front().first);
resque.pop();
}
}
return 0;
}