poj3565 Ants

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章