一定要清楚的一个问题,就是:(如图)两条黑色的线的和一定小于蓝色的和,但是平方的和之间就不一定是这个关系了!
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; const double INF = 0x7fffffff; const double eps = 1e-9; const int N = 110; int n; double w[N][N], lx[N], ly[N]; int l[N], r[N]; int wx[N], wy[N], bx[N], by[N]; bool S[N], T[N]; bool eq( double x, double y ) { return fabs ( x - y ) < eps; } bool match( int i ) { S[i] = true; for ( int j = 1; j <= n; ++j ) if ( eq( lx[i] + ly[j], w[i][j] ) && !T[j] ) { T[j] = true; if ( !l[j] || match(l[j]) ) { l[j] = i; //r[i] = j; return true; } } return false; } void update() { double a = INF; for ( int i = 1; i <= n; ++i ) if ( S[i] ) for ( int j = 1; j <= n; ++j ) if ( !T[j] ) a = min( a, lx[i]+ly[j]-w[i][j] ); for ( int i = 1; i <= n; ++i ) { if ( S[i] ) lx[i] -= a; if ( T[i] ) ly[i] += a; } } void KM() { //memset(l, 0, sizeof(l)); //memset(r, 0, sizeof(r)); for ( int i = 1; i <= n; ++i ) { l[i] = lx[i] = ly[i] = 0; for ( int j = 1; j <= n; ++j ) lx[i] = max( lx[i], w[i][j] ); } for ( int i = 1; i <= n; ++i ) { for(;;) { for ( int j = 1; j <= n; ++j ) S[j] = T[j] = 0; if ( match(i) ) break; else update(); } } } int main() { bool first = false; while ( scanf("%d", &n) != EOF ) { if ( first ) printf("\n"); first = true; for ( int i = 1; i <= n; ++i ) scanf("%d%d", &wx[i], &wy[i]); for ( int i = 1; i <= n; ++i ) scanf("%d%d", &bx[i], &by[i]); for ( int i = 1; i <= n; ++i ) for ( int j = 1; j <= n; ++j ) w[j][i] = -sqrt((double)(wx[i]-bx[j])*(wx[i]-bx[j])+(double)(wy[i]-by[j])*(wy[i]-by[j])); KM(); for ( int i = 1; i <= n; ++i ) printf("%d\n", l[i]); } }