使用KM算法,我写过一个,思路是把蚂蚁和树分为两个集合,但是莫名其妙的错了,然后在网上又查了一段代码,和我的方法相同,甚至代码内容差不多,但人家A了,郁闷啊。。。求助。
错误代码:
#include<iostream> #include<cmath> using namespace std; const int MAXN = 101; const int inf = 0x3ffffff; double edge[MAXN][MAXN]; bool vis_x[MAXN],vis_y[MAXN]; double lx[MAXN],ly[MAXN]; int result[MAXN]; struct points { double x;double y; }vetex[2*MAXN]; bool find(int a,int n) { vis_x[a] = true; for(int i=1;i!=n+1;i++) { if(!vis_y[i]&&edge[a][i] == lx[a] + ly[i]) { vis_y[i] = true; if(result[i]==-1||find(result[i],n)) { result[i] = a; return true; } } } return false; } void KM(int n) { for(int i=1;i!=n+1;i++) { lx[i] = -inf; ly[i] = 0; for(int j=1;j!=n+1;j++) if (lx [i] < edge [i] [j]) lx [i] = edge [i] [j]; } memset(result,-1,sizeof(result)); for(int u = 1;u!=n+1;u++) { while(1) { memset(vis_x,0,sizeof(vis_x)); memset(vis_y,0,sizeof(vis_y)); if(find(u,n)) break; double dx = inf; for (int i = 1; i<=n+1;i++) if (vis_x [i]) for (int j = 1; j<=n+1;j++) if(!vis_y [j]) dx = min (lx[i]+ly[j]-edge[i][j],dx); for (int i = 1;i <= n+1;i++) { if (vis_x[i]) lx[i] -= dx; if (vis_y[i]) ly[i] += dx; } } } for(int i=1;i!=n+1;i++) { cout<<result[i]<<endl; } } int main() { int T; while(cin>>T) { memset(edge,0,sizeof(edge)); for(int k=1;k!=2*T+1;k++) cin>>vetex[k].x>>vetex[k].y; for(int k=1;k!=T+1;k++) { for(int j=T+1;j!=2*T+1;j++) { double num1 = (vetex[k].x-vetex[j].x)*(vetex[k].x-vetex[j].x); double num2 = (vetex[k].y-vetex[j].y)*(vetex[k].y-vetex[j].y); num1+=num2; edge[k][j-T] = -sqrt(num1); } } KM(T); } return 0; }正确代码:
#include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> #define inf 99999999.0 using namespace std; struct Point { double x; double y; }; Point ant[105]; Point tree[105]; double map[105][105]; int link[105]; double lx[105]; double ly[105]; bool x[105]; bool y[105]; int n; double dist(Point a,Point b) { return -sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void init() { int i,j; for(i=0;i<105;i++) { lx[i]=inf; ly[i]=0; link[i]=-1; } for(i=0;i<105;i++) for(j=0;j<105;j++) map[i][j]=0; } bool judge(int v,int i) { double esp; esp=0.0001; double r=lx[v]+ly[i]; double z=map[v][i]; if(abs(r-z)<=esp) return true; else return false; } bool find(int v) { int i; x[v]=true; for(i=1;i<=n;i++) { if(!y[i]&&judge(v,i)) { y[i]=true; if(link[i]==-1||find(link[i])) { link[i]=v; return true; } } } return false; } int main() { int i,j,k; double d; init(); scanf("%d",&n); for(i=1;i<=n;i++) scanf("%lf%lf",&ant[i].x,&ant[i].y); for(i=1;i<=n;i++) scanf("%lf%lf",&tree[i].x,&tree[i].y); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { map[i][j]=dist(ant[i],tree[j]); // printf("%lf ",map[i][j]); } // printf("/n"); } for(k=1;k<=n;k++) { while(1) { memset(x,0,sizeof(x)); memset(y,0,sizeof(y)); if(find(k)) break; d=inf; for(i=1;i<=n;i++) if(x[i]) for(j=1;j<=n;j++) if(!y[j]&&(lx[i]+ly[j]-map[i][j]<d)) d=lx[i]+ly[j]-map[i][j]; for(i=1;i<=n;i++) if(x[i]) lx[i]=lx[i]-d; for(i=1;i<=n;i++) if(y[i]) ly[i]=ly[i]+d; } } double uva=0.0; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(link[j]==i) { printf("%d\n",j); break; } } system("pause"); return 0; }