POJ 1034--The dog task

题意

Bob和小狗散步,他的路线可以构成一个N边形(可能是自交的).小狗的速度是Bob的两倍,它会四处跑动,但是小狗总能在多边形顶点处与Bob相遇.小狗的目标可能是树,蘑菇,土丘等,但是每次与Bob相遇前,小狗最多能去一个目标.求出从散步出发到结束小狗最多能去多少个目标,并且输出小狗移动路线坐标(Bob路线多边形的顶点和小狗去过的目标的坐标).

分析

  • 考虑边A-B,在这条边周围可能有若干个小狗可以去的目标.但是要想小狗在A处与Bob分离同时在B处与Bob相遇,那么目标必然在以A, B点为焦点的椭圆范围之内(椭圆特性).
  • 通过计算,得到每一条边周围小狗能到达的目标,这些目标组成集合S1、S2、S3,但是同一个目标可能同时出现在多个集合内.因此,要找出一个最大匹配的情况,这里采用的二分图求最大匹配的匈牙利算法(暂不介绍).

代码如下:
Memory: 964K Time: 610MS Length: 114LINES

#include <iostream>
#include <cmath>
#include <cstring>
#include <set>
using namespace std;

double cost = 0.0;
double sint = 0.0;
double long_semi_axial = 0.0;
double short_semi_axial = 0.0;
int opt = 0;
int arg[2] = { 1, -1 };
double xoffset, yoffset;

struct point_t {
    int x, y;
    int idx;
    point_t() {x = 0; y = 0; idx = -1;}
};

struct line_t {
    point_t p1, p2;
    set<int> p_set_cand;
    int final_rst;
    line_t() {final_rst = -1;}
};

void insert(line_t& pl, point_t* pp, int idx)
{
    double x = double(pp[idx].x);
    double y = double(pp[idx].y);
    if (pow(((x - xoffset) * cost - (y - yoffset) * sint * arg[opt]) / long_semi_axial, 2.0) + 
        pow(((x - xoffset) * sint + (y - yoffset) * cost * arg[opt]) / short_semi_axial, 2.0) < 1.0) {
        pl.p_set_cand.insert(idx);
    }
}

void compute(line_t& line)    //计算椭圆的参数
{
    opt = (line.p2.x - line.p1.x) * (line.p2.y - line.p1.y) > 0 ? 1 : 0;
    long_semi_axial = sqrt(pow(line.p2.x - line.p1.x, 2.0) + pow(line.p2.y - line.p1.y, 2.0));
    short_semi_axial = long_semi_axial / 2.0 * sqrt(3.0);
    cost = (line.p2.x - line.p1.x) / long_semi_axial;
    sint = (line.p2.y - line.p1.y) / long_semi_axial;
    cost = cost > 0 ? cost : -cost;
    sint = sint > 0 ? sint : -sint;
    xoffset = (line.p2.x + line.p1.x) / 2.0;
    yoffset = (line.p2.y + line.p1.y) / 2.0; 
}

bool search(line_t* line, int idx, point_t* pp, bool* flag) {
    for (set<int>::iterator it = line[idx].p_set_cand.begin(); it != line[idx].p_set_cand.end(); ++it) {
        if (!flag[*it]) {
            flag[*it] = true;
            if (pp[*it].idx == -1 || search(line, pp[*it].idx, pp, flag)) {
                pp[*it].idx = idx;
                line[idx].final_rst = *it;
                return true;
            }
        }
    }
    return false;
}

int main() {
    int line_cnt;
    int inters_cnt;
    cin >> line_cnt >> inters_cnt;
    --line_cnt;
    line_t* p_line = new line_t[line_cnt];
    point_t* p_dog_pos = new point_t[inters_cnt];
    for (int i = 0; i < line_cnt; ++i) {
        if (i == 0) {
            cin >> p_line[i].p1.x >> p_line[i].p1.y;
        } else {
            p_line[i].p1.x = p_line[i - 1].p2.x;
            p_line[i].p1.y = p_line[i - 1].p2.y;
        }
        cin >> p_line[i].p2.x >> p_line[i].p2.y;
    }

    for (int i = 0; i < inters_cnt; ++i) {
        cin >> p_dog_pos[i].x >> p_dog_pos[i].y;
    }

    for (int i = 0; i < line_cnt; ++i) {
        compute(p_line[i]);
        for (int j = 0; j < inters_cnt; ++j) {
            insert(p_line[i], p_dog_pos, j);
        }
    }
    bool* flag = new bool[inters_cnt];
    int done = 0;
    for (int i = 0; i < line_cnt; ++i) {
        memset(flag, false, inters_cnt);
        if (search(p_line, i, p_dog_pos, flag)) {
            ++done;
        }
    }

    cout << done + line_cnt + 1 << endl;
    cout << p_line[0].p1.x << " " << p_line[0].p1.y;
    for (int i = 0; i < line_cnt; ++i) {
        if (p_line[i].final_rst != -1) {
            cout << " " << p_dog_pos[p_line[i].final_rst].x << " " << p_dog_pos[p_line[i].final_rst].y;
        }
        cout << " " << p_line[i].p2.x << " " << p_line[i].p2.y;
    }
    cout << endl;
    delete[] p_line;
    delete[] p_dog_pos;
    delete[] flag;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值