poj 2195

题意:一个row*col的矩阵,m表示人,H表示房子,.表示空地,人数和房子数相等,如下图:

        5 5
        HH..m
        .....
        .....
        .....
        mm..H
现在要让所有的人都进入不同的房子内,问总共最少走多少步?

代码:

#include<iostream>
#include<fstream>
#include<queue>
#include<cmath>

using namespace std;
int n,m;

struct e{
	int data;
	int c,f,w;
	e *next;
	e *op;
};

e edge[400];

int x[101],y[101],xx[101],yy[101];
int n1,n2;
int start=0,end=1;
int total;
int d[400];
int v[400];
e *path[400];
int pa[400];

int spfa(){
	int i,j,k;
	for(i=0;i<=total;i++)
		d[i]=10000000;
	memset(v,0,sizeof(v));
	d[start]=0;
	priority_queue<int> q;
	q.push(start);
	v[start]=1;
	path[start]=0;
	pa[start]=-1;

	while(!q.empty()){
		i=q.top();
		v[i]=0;
		q.pop();
		e *p=edge[i].next;
		while(p){
			if(p->c>p->f&&d[p->data]>d[i]+p->w)
			{
				d[p->data]=d[i]+p->w;
				path[p->data]=p;
				pa[p->data]=i;
				if(v[p->data]==0)
				{
					v[p->data]=1;
					q.push(p->data);
				}
			}
			p=p->next;
		}
	}
	if(d[end]==10000000) return 0;
	else
		return d[end];
}

void solve(){
	total=2*n1+1;
	int i,j,k,s;
	int w=0;
	int flow=0;
	while(s=spfa())
	{
		
		k=10000000;
		j=end;
		while(pa[j]!=-1)
		{
			k=min(path[j]->c-path[j]->f,k);
			j=pa[j];	
		}
		j=end;
		while(pa[j]!=-1)
		{
			path[j]->f+=k;
			path[j]->op->f=-1*path[j]->f;
			j=pa[j];
		}
		w+=s*k;
		flow+=k;
	}
	cout<<w<<endl;
//	cout<<flow<<endl;
}

void add(int s,int t,int value,int w){
	e *p=new e;
	p->data=t;
	p->c=value;
	p->f=0;
	p->w=w;
	p->next=edge[s].next;
	edge[s].next=p;

	e *q=new e;
	q->data=s;
	q->c=q->f=0;
	q->w=-w;
	q->next=edge[t].next;
	edge[t].next=q;
	
	p->op=q;
	q->op=p;
}

void read(){
//	ifstream cin("in.txt");
	int i,j,k;
	char c;
	while(cin>>n>>m)
	{
		if(n==0&&m==0) return ;
		n1=0;
		n2=0;
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
			{
				cin>>c;
				if(c=='H')
				{
					x[++n1]=i;
					y[n1]=j;
				}
				if(c=='m')
				{
					xx[++n2]=i;
					yy[n2]=j;
				}
			}
		for(i=0;i<=n1*2+1;i++)
			edge[i].next=0;
		for(i=2;i<=n1+1;i++)
			add(0,i,1,0);
		for(i=n1+2;i<=n1*2+1;i++)
			add(i,1,1,0);
		for(i=1;i<=n1;i++)
			for(j=1;j<=n2;j++)
				add(i+1,j+n1+1,1,abs(x[i]-xx[j])+abs(y[i]-yy[j]));
		solve();

	}

}

int  main(){
	read();
	return 0;
}

posted on 2011-05-18 17:50  宇宙吾心  阅读(999)  评论(0)    收藏  举报

导航