Bender Problem

Bender Problem


Robot Bender decided to make Fray a birthday present. He drove n nails and numbered them from 1 to n in some order. Bender decided to make a picture using metal rods. The picture is a closed polyline, which vertices should be nails (in the given order). The segments of the polyline should be parallel to the coordinate axes. Polyline is allowed to have self-intersections. Bender can take a rod and fold it exactly once in any place to form an angle of 90 degrees. Then he can attach the place of the fold to some unoccupied nail and attach two ends of this rod to adjacent nails. A nail is considered unoccupied if there is no rod attached to it (neither by it's end nor the by the fold place). No rod could be used twice. It is not required to use all the rods.

Help Bender to solve this difficult task.

Input

The first line contains two positive integers n and m (4 ≤ n ≤ 500, 2 ≤ m ≤ 500, n is even) — the amount of nails and the amount of rods. i-th of the following n lines contains a pair of integers, denoting the coordinates of the i-th nail. Nails should be connected in the same order as they are given in the input. The last line contains m integers — the lenghts of the rods. All coordinates do not exceed 104 by absolute value. Lengths of the rods are between 1 and 200 000. No rod can be used twice. It is guaranteed that all segments of the given polyline are parallel to coordinate axes. No three consecutive nails lie on the same line.

Output

If it is impossible to solve Bender's problem, output NO. Otherwise, output YES in the first line, and in the second line output n numbers — i-th of them should be the number of rod, which fold place is attached to the i-th nail, or -1, if there is no such rod.

If there are multiple solutions, print any of them.

Example
Input
4 2
0 0
0 2
2 2
2 0
4 4
Output
YES
1 -1 2 -1 
Input
6 3
0 0
1 0
1 1
2 1
2 2
0 2
3 2 3
Output
YES
1 -1 2 -1 3 -1 
Input
6 3
0 0
1 0
1 1
2 1
2 2
0 2
2 2 3
Output
NO


这道题主要是题意比较难理解。

题意:有n个钉子,从1~n编号,有m条铁棒,要求用这些铁棒和钉子围成一个封闭的折线。要求铁棒不一定全部用完,铁棒必须平行于坐标轴(这句话说明所有钉子的位置,两两之间的连线一定也是平行于坐标轴的)。现在他要把铁棒完成直角,这样中间的折叠点一个钉子,两头各一个钉子,要求折叠的这颗钉子之前必须是没有别的棒连接的(也就是空钉子),问怎么选棒,棒只能用一次

思路:首先会发现每段会占用三个钉子,而折叠点处需要的钉子是最特殊的,所以我们应该枚举折叠点处的钉子,我们假设折叠点处是i号钉子,那么两头就是i-1号和i+1号钉子,这样i-1到i到i+1的最短折线距离是所需要的棒的长度,所以用两重循环先枚举折叠点,然后算出所需棒的长度,再从所有棒中找恰好等于这个长度的棒有没有

具体怎么枚举:我们发现如果第一个折叠点在1号钉子处,那么下一个折叠点应该在3号,5,7,9……,如果第一个折叠点在2号钉子处,之后的折叠点应该在4,6,8……,所以枚举两次,如果从1开始枚举可以围成封闭折线直接输出,否则在从2开始枚举,如果都不行就说明不可以,反之输出答案。

code:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 505;
int n,m;
struct nail{
    int x,y;
}a[MAXN];
int len[MAXN];
int vis[MAXN];
int ans[MAXN];

int judge(int i,int j){
    return len[j] == ((abs(a[i-1].x-a[i].x)+abs(a[i-1].y-a[i].y))+(abs(a[i+1].x-a[i].x)+abs(a[i+1].y-a[i].y)));
}
void print(){
    int i;
    puts("YES");
    for(i = 1; i <= n; i++){
        if(i == 1)
            printf("%d",(ans[i]?ans[i]:-1));
        else
            printf(" %d",(ans[i]?ans[i]:-1));
    }
}

int main(){
    int i,j;
    int flag,t = 0;
    memset(vis,0,sizeof(vis));
    memset(ans,0,sizeof(ans));
    scanf("%d%d",&n,&m);
    for(i = 1; i <= n; i++)
        scanf("%d%d",&a[i].x,&a[i].y);
    for(i = 1; i <= m; i++)
        scanf("%d",&len[i]);
    a[0].x = a[n].x;
    a[0].y = a[n].y;
    a[n+1].x = a[1].x;
    a[n+1].y = a[1].y;
    for(i = 1; i <= n; i += 2){//从1开始枚举折叠点
        flag = 0;
        for(j = 1; j <= m; j++){
            if(!vis[j] && judge(i,j)){
                flag = 1;
                vis[j] = 1;
                ans[i] = j;
                break;
            }
        }
        if(!flag){
            t = 1;
            break;
        }
    }
    if(!t){//如果符合输出答案
        print();
    }
    else{//否则从二开始枚举折叠点
        memset(vis,0,sizeof(vis));
        memset(ans,0,sizeof(ans));
        for(i = 2; i <= n; i += 2){
            flag = 0;
            for(j = 1; j <= m; j++){
                if(!vis[j] && judge(i,j)){
                    flag = 1;
                    vis[j] = 1;
                    ans[i] = j;
                    break;
                }
            }
            if(!flag){
                printf("NO\n");
                return 0;
            }
        }
        print();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值