题意
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;
}