题目背景
Grant喜欢带着他的小狗Pandog散步。Grant以一定的速度沿着固定路线走,该路线可能自交。Pandog喜欢游览沿途的景点,不过会在给定的N个点和主人相遇。小狗和主人同时从(X1,Y1)点出发,并同时在(Xn,Yn)点汇合。小狗的速度最快是Grant的两倍。当主人从一个点以直线走向另一个点时,Pandog跑向一个它感兴趣的景点。Pandog每次与主人相遇之前最多只去一个景点。
题目描述
你现在的任务是:为Pandog寻找一条路线(有可能与主人的路线部分相同),使它能够游览最多的景点,并能够准时与主人在给定地点相遇或者汇合。
输入输出格式
输入格式:
输入文件第一行是两个整数N和M( 1≤N,M≤100 );
输入文件第二行的N个坐标给出了Grant的散步路线,即Pandog和主人相遇地点;
输入文件第三行的M个坐标给出了所有Pandog感兴趣的景点。
所有输入的坐标均不相同,且绝对值不超过1000。
输出格式:
输出小狗的移动路线。
第一行是经过的点数,第二行依次为经过的点的坐标(直角坐标系)
输入输出样例
输入样例#1:
4 5
1 4 5 7 5 2 -2 4
-4 -2 3 9 1 2 -1 3 8 -3
输出样例#1:
6
1 4 3 9 5 7 5 2 1 2 -2 4
说明
"The way is wrong!"表示输出方案错误(可能是坐标不存在输入文件中,两个相遇点间存在多个景点,或距离超出范围)
解题思路
把每条路的长度计算出来,把小狗想去的坐标和每段路两个顶点之间的距离和也算出来,如果路程小于等于路的两倍,说明小狗可以来得及去,也就是可以匹配。然后求最大匹配即可。至于那个说明,,才看到,没理它也过了。
代码如下
#include <iostream>
#include <cstring>
#include <cmath>
#define maxn 1005
using namespace std;
bool g[maxn][maxn];
struct loc{
double x, y;
}a[maxn], b[maxn];
int pre[maxn];
int n, m;
bool vis[maxn];
bool dfs(int x)
{
for(int i = 1; i < n; i ++){
if(!vis[i] && g[x][i]){
vis[i] = true;
if(!pre[i] || dfs(pre[i])){
pre[i] = x;
return true;
}
}
}
return false;
}
void max_match()
{
int ans = n;
memset(pre, 0, sizeof(pre));
for(int i = 1; i <= m; i ++){
memset(vis, 0, sizeof(vis));
ans += dfs(i);
}
cout << ans << endl;
cout << a[1].x << " " << a[1].y;
for(int i = 1; i < n; i ++){
if(pre[i])
cout << " " << b[pre[i]].x << " " << b[pre[i]].y;
cout << " " << a[i + 1].x << " " << a[i + 1].y;
}
cout << endl;
}
int main()
{
while(cin >> n >> m){
memset(g, 0, sizeof(g));
double u[maxn];
for(int i = 1; i <= n; i ++){
cin >> a[i].x >> a[i].y;
if(i != 1){
u[i - 1] = sqrt((a[i].y-a[i-1].y) * (a[i].y-a[i-1].y) + (a[i].x-a[i-1].x) * (a[i].x-a[i-1].x));
}
}
for(int i = 1; i <= m; i ++){
double x, y;
cin >> x >> y;
b[i].x = x;
b[i].y = y;
for(int j = 1; j < n; j ++){
double dis = sqrt((a[j].y-y)*(a[j].y-y)+(a[j].x-x)*(a[j].x-x))
+ sqrt((a[j+1].y-y)*(a[j+1].y-y)+(a[j+1].x-x)*(a[j+1].x-x));
if(dis <= u[j] * 2.0)
g[i][j] = true;
}
}
max_match();
}
return 0;
}