使用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;
}