巨人与鬼

巨人和鬼

一组n个巨人正与n个鬼进行战斗,每个巨人的武器是一个质子炮, 它可以把一串质子流射中鬼而把鬼消灭。质子流沿直线行进,在击中鬼时就终止。巨人决定采取下述策略。他们寻找鬼配对,以形成n个巨人─鬼对,。然后每个巨人同时向他选取的鬼射出一串质子流。我们知道,让质子流互相交叉是很危险的。因此巨人选择的配对方式应该使质子流都不会交叉。假定每个巨人和每个鬼的位置都是平面上的一个固定点,并且没有三个位置共线, 求一种配对方案。

解题思路:由题意知,其必存在一个解,这里利用分治的思想,利用一条线,把原区域分为两个区域,然后对这两个区域递归求解。

分割思路:

1.先找左下角节点

2.把其余点按其与左下角节点角度大小排序

3.从小到大遍历,当一边的巨人与鬼的数量相同时(这里利用正负1相加为0判断),储存答案,递归求解

分割图如下:

用p1 –p6分割

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct node {
    int biao, x, y;//序号和坐标
    bool id;//标识巨人还是鬼
};
int n;
node p[1000],ji;
int ans[1000];
bool cmp(node &a, node &b) {
    return a.y != b.y ? a.y < b.y : a.x < b.x;
}
bool cmp1(node &a, node &b) {
    return (atan2((a.y - ji.y),(a.x - ji.x))<atan2((b.y - ji.y),(b.x - ji.x)));
}
void go(int l,int r) {
    if (l > r)
        return;
    sort(p + l, p + r + 1, cmp);//获取最左下的点作为基点
    ji = p[l];
    sort(p + l + 1, p + r + 1, cmp1);//根据其他点与基点连线和水平线的角度进行排序
    int c1 = 0, c2 = 0;
    int k = r;
    while (!(ji.id != p[k].id&&c1 == c2)) {
        if (p[k].id == ji.id)c1++;//c1是相同标识的数量
        else c2++;//c2是与基点不同标识的数量
        k--;
    }
    ans[p[k].biao] = ji.biao;//只有当c1与c2的数量相等且基点与当前点标识不同时才能配对
    ans[ji.biao] = p[k].biao;
    go(l + 1, k - 1);//左半部分
    go(k + 1, r);//右半部份
}
int main(void) {
    while (cin >> n) {
        for (int i = 1; i <= n; i++) {
            cin >> p[i].x >> p[i].y >> p[i].id;
            p[i].biao = i;
        }
        go(1, n);
        for (int i = 1; i <= n; i++)
            cout << ans[i]<<" ";
    }
    system("pause");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值