poj2195 Going Home

来源:互联网 发布:黑马c语言视频云盘 编辑:程序博客网 时间:2024/06/14 11:18

题义:在一个图上,n个人回n个家,可以路过家门而不进去,图中m代表人,H代表家,每人走一步,需要花费1元,求要是这些人都回家,最少花多少。

分析:看到题目后首先可以想到的就是人和家是2个集合,人不能与人相连,家也不能与家相连,那么就可给人和家编号,从而构造出一幅2分图,由于可以过门而不入,就说明途中没有障碍物,这就意味着不必去广搜,直接找坐标之间的关系,来确定两点之间的开销。

只是一道KM算法求最小匹配的简单问题(还可以用网络流实现)。

#include<iostream>#include<vector>#include<cmath>using namespace std;const int MAXN = 110;const int inf = -0x3ffffff;struct node{int pos_x,pos_y;int node_num;node(){pos_x=0,pos_y=0;    node_num=0;}};int bin_map[MAXN][MAXN];char ch[MAXN][MAXN];bool vis_x[MAXN],vis_y[MAXN];int lx[MAXN],ly[MAXN];int result[MAXN];bool find(int a,int n)//判断第a能否找到房子{vis_x[a] = true;for(int i=1;i!=n;i++){if(!vis_y[i]&&bin_map[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;}int best_match(int n)//开始匹配{memset(ly,0,sizeof(ly));for(int i=1;i!=n;i++){lx[i] = inf;for(int j=1;j!=n;j++){if(lx[i]<bin_map[i][j])lx[i] = bin_map[i][j];}}memset(result,-1,sizeof(result));for(int u=1;u!=n;u++){while(1){memset(vis_x,false,sizeof(vis_x));memset(vis_y,false,sizeof(vis_y));if(find(u,n))//break;int dx = -inf;for(int i=1;i!=n;i++){if(vis_x[i]){for(int j=1;j!=n;j++){if(!vis_y[j])dx = min(dx,lx[i]+ly[j]-bin_map[i][j]);}}}for(int i=1;i!=n+1;i++){if(vis_x[i])lx[i]-=dx;if(vis_y[i])ly[i]+=dx;}}}int sum = 0;for(int i=1;i!=n;i++){sum-=bin_map[result[i]][i];}return sum;}int main(){int m,n;while(cin>>m>>n&&(m!=0&&n!=0)){vector<node> men;vector<node> house;int count_m(0),count_h(0);for(int i=1;i!=m+1;i++){for(int j=1;j!=n+1;j++){cin>>ch[i][j];if(ch[i][j]=='m'){count_m++;node N;N.pos_x = j;N.pos_y = i;N.node_num = count_m;men.push_back(N);}if(ch[i][j]=='H'){count_h++;node N;N.pos_x = j;N.pos_y = i;N.node_num = count_h;house.push_back(N);}}}memset(bin_map,0,sizeof(bin_map));for(vector<node> ::size_type t=0;t!=house.size();t++)//构造二分图{node N1 = men[t]; for(vector<node> ::size_type i=0;i!=house.size();i++){int x2 = house[i].pos_x;int y2 = house[i].pos_y;int x1 = N1.pos_x;int y1 = N1.pos_y;int num = -(abs(x1-x2)+abs(y1-y2));//值变为负数转化为,求最大匹配bin_map[N1.node_num][house[i].node_num] = num; }}int cost = best_match(count_m+1);cout<<cost<<endl;}return 0;}


原创粉丝点击