二分图的最大匹配。
建图的时候从主人路径上的前(n - 1)个点出发,枚举m个景点,能满足条件的连边,然后求最大匹配,输出路径就可以了。
/* * Author: stormdpzh * Created Time: 2012/9/11 20:14:45 * File Name: b.cpp */ #include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <string> #include <cmath> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <list> #include <algorithm> #include <functional> #define sz(v) ((int)(v).size()) #define rep(i, n) for(int i = 0; i < n; i++ #define repf(i, a, b) for(int i = a; i <= b; i++) #define repd(i, a, b) for(int i = a; i >= b; i--) #define out(n) printf("%d\n", n) #define mset(a, b) memset(a, b, sizeof(a)) #define lint long long using namespace std; const int INF = 1 << 30; const int MaxN = 105; const double eps = 1e-8; struct Node { int x, y; void read() { scanf("%d%d", &x, &y); } }; Node pnt[MaxN], dog[MaxN]; int n, m; bool mp[MaxN][MaxN]; int x[MaxN], y[MaxN]; bool vis[MaxN]; int sgn(double d) { if(d > eps) return 1; if(d < -eps) return -1; return 0; } bool check(int id1, int id2) { int xx = pnt[id1 + 1].x - pnt[id1].x; int yy = pnt[id1 + 1].y - pnt[id1].y; double total = xx * xx + yy * yy; int xx1 = dog[id2].x - pnt[id1].x, xx2 = pnt[id1 + 1].x - dog[id2].x; int yy1 = dog[id2].y - pnt[id1].y, yy2 = pnt[id1 + 1].y - dog[id2].y; int total1 = xx1 * xx1 + yy1 * yy1; int total2 = xx2 * xx2 + yy2 * yy2; if(sgn(sqrt((double)total2) + sqrt((double)total1) - 2 * sqrt((double)total)) <= 0) return true; return false; } bool find(int u) { for(int i = 0; i < m; i++) { if(!vis[i] && mp[u][i]) { vis[i] = true; if(y[i] == -1 || find(y[i])) { x[u] = i; y[i] = u; return true; } } } return false; } int gao() { int match = 0; memset(x, -1, sizeof(x)); memset(y, -1, sizeof(y)); for(int i = 0; i < n - 1; i++) { if(x[i] == -1) { memset(vis, false, sizeof(vis)); if(find(i)) match++; } } return match; } int main() { while(2 == scanf("%d%d", &n, &m)) { for(int i = 0; i < n; i++) pnt[i].read(); for(int i = 0; i < m; i++) dog[i].read(); mset(mp, false); for(int i = 0; i < n - 1; i++) { for(int j = 0; j < m; j++) { if(check(i, j)) mp[i][j] = true; } } int res = gao(); printf("%d\n", res + n); for(int i = 0; i < n - 1; i++) { if(x[i] != -1) printf("%d %d %d %d ", pnt[i].x, pnt[i].y, dog[x[i]].x, dog[x[i]].y); else printf("%d %d ", pnt[i].x, pnt[i].y); } printf("%d %d\n", pnt[n - 1].x, pnt[n - 1].y); } return 0; }