POJ 2195 Going Home
2011-08-05 17:09
447 查看
又是一个二分最佳匹配!做过BFS搜索看这题就觉得思路比较清楚了,唯一的就是这次要最小代价!输入的图是一个字符型的!先BFS算距离!然后要处理的就是将距离值取负。这样可以直接用KM!
N次BFS,一次KM,效率还好,可能代码写的略长了!自己的风格,没去简化!
N次BFS,一次KM,效率还好,可能代码写的略长了!自己的风格,没去简化!
#include <iostream> #include <stdio.h> #include <string> #include <queue> usingnamespace std; struct node { int x; int y; int dist; }; #define N 501 char map ;// 输入的图 int map1 ;// 得出的距离图 bool vis ;//BFS 判断点是否走过 int vis2 ;//判断该点是下标 为map1做准备 int link ; //以后是KM准备 int visx ; int visy ; int dx ,dy ; int r; int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};//四方向 int n,m,lack; queue <node > que; void BFS(int k) { node p,q; int i; while(!que.empty()) { p=que.front(); que.pop(); for(i=0;i<4;i++) { int dx=p.x+dir[i][0]; int dy=p.y+dir[i][1]; if(!vis[dx][dy]&&dx>0&&dy>0&&dy<=m&&dx<=n) { vis[dx][dy]=true; q.dist=p.dist+1; q.x=dx; q.y=dy; if(map[dx][dy]=='H') map1[k][vis2[dx][dy]]=-q.dist; //距离取负 转换最大为最小 que.push(q); } } } } int DFS(int v) { int i; visx[v]=1; for(i=1;i<=r;i++) { if(visy[i]) continue; int t=dx[v]+dy[i]-map1[v][i]; if(!t) { visy[i]=true; if(link[i]==-1||DFS(link[i])) { link[i]=v; return1; } } else if(lack>t) lack=t; } return0; } int KM() { int i,j; memset(dx,0,sizeof(dx)); memset(dy,0,sizeof(dy)); memset(link,-1,sizeof(link)); for(i=1;i<=r;i++) { while(true) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); lack=0xffffff; if(DFS(i)) break; for(j=1;j<=r;j++) { if(visx[j]) dx[j]-=lack; if(visy[j]) dy[j]+=lack; } } } int ans=0; for(i=1;i<=r;i++) ans+=dx[i]+dy[i]; return ans; } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF&&(n||m)) { memset(map,'#',sizeof(map)); memset(vis2,0,sizeof(vis2)); int k=1; //用来算多少个点 for(i=1;i<=n;i++) for(j=1;j<=m;j++) { cin>>map[i][j]; if(map[i][j]=='H') vis2[i][j]=k++; } k=1; memset(map1,0,sizeof(map1)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(map[i][j]=='m') { memset(vis,0,sizeof(vis)); node p; while(!que.empty()) que.pop(); p.x=i; p.y=j; p.dist=0; que.push(p); BFS(k); //BFS扫图 k++; } r=k-1; printf("%d\n",-KM()); //答案取负 } return0; } #include <iostream> #include <stdio.h> #include <string> #include <queue> usingnamespace std; struct node { int x; int y; int dist; }; #define N 501 char map ;// 输入的图 int map1 ;// 得出的距离图 bool vis ;//BFS 判断点是否走过 int vis2 ;//判断该点是下标 为map1做准备 int link ; //以后是KM准备 int visx ; int visy ; int dx ,dy ; int r; int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};//四方向 int n,m,lack; queue <node > que; void BFS(int k) { node p,q; int i; while(!que.empty()) { p=que.front(); que.pop(); for(i=0;i<4;i++) { int dx=p.x+dir[i][0]; int dy=p.y+dir[i][1]; if(!vis[dx][dy]&&dx>0&&dy>0&&dy<=m&&dx<=n) { vis[dx][dy]=true; q.dist=p.dist+1; q.x=dx; q.y=dy; if(map[dx][dy]=='H') map1[k][vis2[dx][dy]]=-q.dist; //距离取负 转换最大为最小 que.push(q); } } } } int DFS(int v) { int i; visx[v]=1; for(i=1;i<=r;i++) { if(visy[i]) continue; int t=dx[v]+dy[i]-map1[v][i]; if(!t) { visy[i]=true; if(link[i]==-1||DFS(link[i])) { link[i]=v; return1; } } else if(lack>t) lack=t; } return0; } int KM() { int i,j; memset(dx,0,sizeof(dx)); memset(dy,0,sizeof(dy)); memset(link,-1,sizeof(link)); for(i=1;i<=r;i++) { while(true) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); lack=0xffffff; if(DFS(i)) break; for(j=1;j<=r;j++) { if(visx[j]) dx[j]-=lack; if(visy[j]) dy[j]+=lack; } } } int ans=0; for(i=1;i<=r;i++) ans+=dx[i]+dy[i]; return ans; } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF&&(n||m)) { memset(map,'#',sizeof(map)); memset(vis2,0,sizeof(vis2)); int k=1; //用来算多少个点 for(i=1;i<=n;i++) for(j=1;j<=m;j++) { cin>>map[i][j]; if(map[i][j]=='H') vis2[i][j]=k++; } k=1; memset(map1,0,sizeof(map1)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(map[i][j]=='m') { memset(vis,0,sizeof(vis)); node p; while(!que.empty()) que.pop(); p.x=i; p.y=j; p.dist=0; que.push(p); BFS(k); //BFS扫图 k++; } r=k-1; printf("%d\n",-KM()); //答案取负 } return0; }
相关文章推荐
- poj 2195 Going Home
- POJ 2195 Going Home
- poj 2195 Going Home
- POJ 2195 Going Home
- 最小费用最大流-POJ-2195-Going Home
- poj 2195 Going Home
- POJ 2195--Going Home
- poj 2195 Going Home 二分图最大权匹配
- POJ 2195 Going Home
- POJ 2195 Going Home
- POJ 2195:Going Home(SPFA最小费用最大流)
- POJ 2195 Going Home 最小费用流 难度:1
- POJ 2195 Going Home(费用流)
- poj 2195 Going Home 二分图最大权匹配
- KM算法 最优匹配(最大权匹配) hdu 2255 奔小康赚大钱 最小权匹配 poj 2195 Going Home
- poj 2195 Going Home
- POJ 2195 Going Home 已翻译
- poj 2195 - Going Home 二分图最优匹配 ek
- POJ-2195 Going Home
- POj 2195 Going Home(费用流)