『题解』CF28A Bender Problem
题意
有 \(n\) 个钉子,从 \(1 \sim n\) 编号,有 \(m\) 条铁棒,要求用这些铁棒和钉子围成一个封闭的折线。要求铁棒不一定全部用完,铁棒必须平行于坐标轴。
现在他要把铁棒弯成直角,这样中间的折叠点一个钉子,两头各一个钉子,要求折叠的这颗钉子之前必须是没有别的棒连接的(也就是空钉子),问怎么选棒,棒只能用一次。
如果无法解决 Bender 的问题,请输出 NO
。否则,在第一行中输出 YES
,在第二行中输出 \(n\) 个数字,其中第 \(i\) 个数表示杆的数量,该折叠位置固定在第 \(i\) 个钉上;如果没有这样的杆,则输出 \(-1\) 。
思路
用铁棒把钉子框起来,每个铁棒只能折叠一次。
由题意我们可以得出,如果一个铁棒在第 \(i\) 个钉子处折叠,那么第 \(i+1\) 个就一定不是折叠的。
题目中钉子按顺序给出,所以我们只需要枚举每个钉子,判断是奇数或者偶数点,看是否满足即可。
注意初始条件。
CODE
/*
Name: CF28A Bender Problem
Solution: 瞎搞
By Frather_
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define ll long long
#define InF 0x3f3f3f3f
#define kMax 10e5
#define kMin -10e5
#define kMod 998244353
using namespace std;
/*==================================================快读*/
inline int read()
{
int X = 0, F = 1;
char CH = getchar();
while (CH < '0' || CH > '9')
{
if (CH == '-')
F = -1;
CH = getchar();
}
while (CH >= '0' && CH <= '9')
{
X = (X << 3) + (X << 1) + (CH ^ 48);
CH = getchar();
}
return X * F;
}
/*===============================================定义变量*/
int n, m;
const int _ = 10010;
int x[_], y[_], rod[_], ans[_];
bool vis[_];
bool flag;
/*=============================================自定义函数*/
int Calc(int i, int j)
{
int x_ = abs(x[j] - x[(j + n - 1) % n]);
int y_ = abs(y[j] - y[(j + n - 1) % n]);
int _x = abs(x[j] - x[(j + 1) % n]);
int _y = abs(y[j] - y[(j + 1) % n]);
return x_ + y_ + _x + _y;
}
void prepare()
{
memset(ans, -1, sizeof(ans)); //判断是否折叠
memset(vis, false, sizeof(vis));
flag = true;
}
/*=================================================主函数*/
signed main()
{
n = read();
m = read();
for (int i = 0; i < n; i++)
{
x[i] = read();
y[i] = read();
}
for (int i = 0; i < m; i++)
rod[i] = read();
for (int i = 0; i < 2; i++)
{
prepare();
for (int j = i; j < n; j += 2)
{
int dis = Calc(i, j); //当前钉子与前一个或后一个的距离
for (int k = 0; k < m; k++)
{
if (!vis[k] && rod[k] == dis)
{
vis[k] = true;
ans[j] = k + 1;
break;
}
}
if (ans[j] == -1)
{
flag = false;
break;
}
}
if (flag)
break;
}
if (flag)
{
printf("YES\n%d", ans[0]);
for (int i = 1; i < n; i++)
printf(" %d", ans[i]);
puts("");
}
else
printf("NO\n");
return 0;
}