Uva 10888 Warehouse(KM)
来源:互联网 发布:计算机的发展史知乎 编辑:程序博客网 时间:2024/06/06 12:31
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1829
思路:
1.首先求出每个箱子到达每个目的地的最短距离w。
2.将箱子看做x点,将目的地看做y点,x向y连边,权值为w,求二分图最优匹配即可。
3.是否存在移动过程中路径上有其他箱子阻挡。例如,从A到C的路径上存在B箱子,则此时可以看做将B箱子移动到C后,A移动到B箱子。即最优匹配一定对应着一组可行解。
#include<map>#include<queue>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define F first#define S second#define pii pair<int,int>#define debugusing namespace std;const int N = 20;const int maxn = 45;const int INF = 0x3f3f3f3f;int nx,ny;//两边的点数int g[N][N];//二分图描述int linker[N],lx[N],ly[N];int slack[N];bool visx[N],visy[N];bool DFS(int x){ visx[x] = true; for(int y = 0; y < ny; y++) { if(visy[y])continue; int tmp = lx[x] + ly[y] - g[x][y]; if(tmp == 0) { visy[y] = true; if(linker[y] == -1 || DFS(linker[y])) { linker[y] = x; return true; } } else if(slack[y] > tmp) slack[y] = tmp; } return false;}int KM(){ memset(linker,-1,sizeof(linker)); memset(ly,0,sizeof(ly)); for(int i = 0; i < nx; i++) { lx[i] = -INF; for(int j = 0; j < ny; j++) if(g[i][j] > lx[i]) lx[i] = g[i][j]; } for(int x = 0; x < nx; x++) { for(int i = 0; i < ny; i++) slack[i] = INF; while(true) { memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if(DFS(x))break; int d = INF; for(int i = 0; i < ny; i++) if(!visy[i] && d > slack[i]) d = slack[i]; for(int i = 0; i < nx; i++) if(visx[i]) lx[i] -= d; for(int i = 0; i < ny; i++) { if(visy[i])ly[i] += d; else slack[i] -= d; } } } int res = 0; for(int i = 0; i < ny; i++) if(linker[i] != -1) res += g[linker[i]][i]; return res;}struct Node{ pii p; int step; Node() {} Node(pii p,int step):p(p),step(step) {}};int n,m;int cntB,cntE;int vis[maxn*maxn];char ch[maxn][maxn];int dx[]= {-1,1,0,0};int dy[]= {0,0,-1,1};queue<Node> q;map<pii,int> box,ed;void init(){ cntB=cntE=0; box.clear(),ed.clear();}inline int ID(int x,int y){ return x*m+y;}inline int isIn(int x,int y){ return x>=1&&x<=n&&y>=1&&y<=m;}void build(pii p,int id){ memset(vis,0,sizeof(vis)); while(!q.empty()) q.pop(); q.push(Node(p,0)); vis[ID(p.F,p.S)]=1; while(!q.empty()) { Node now=q.front(); q.pop(); for(int i=0; i<4; i++) { int x=now.p.F+dx[i]; int y=now.p.S+dy[i]; if(isIn(x,y)&&!vis[ID(x,y)]&&ch[x][y]!='#') { if(ch[x][y]=='X') { g[id][ed[make_pair(x,y)]]=-(now.step+1); } vis[ID(x,y)]=1; q.push(Node(make_pair(x,y),now.step+1)); } } }}void solve(){ for(int i=0;i<box.size();i++) { for(int j=0;j<box.size();j++) { g[i][j]=-INF; } } int cnt=0; map<pii,int>::iterator it=box.begin(); for(; it!=box.end(); it++) { build(it->F,cnt++); } nx=ny=cnt; printf("%d\n",-KM());}int main(){#ifdef debu freopen("in.txt","r",stdin);#endif // debug int t; scanf("%d",&t); while(t--) { init(); scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { getchar(); for(int j=1; j<=m; j++) { scanf("%c",&ch[i][j]); if(ch[i][j]=='B') box[make_pair(i,j)]=cntB++; else if(ch[i][j]=='X') ed[make_pair(i,j)]=cntE++; } } solve(); } return 0;}
阅读全文
0 0
- Uva 10888 Warehouse(KM)
- UVA 10888 - Warehouse(最小费用流)
- UVa:10888 Warehouse
- (intermediate) 最小权匹配 UVA 10888 - Warehouse
- UVA 10888 - Warehouse(二分图完美匹配)
- UVA-11383 (KM算法)
- Uva 10888 Warehouse(二分图最大权匹配)
- UVA 10888 km 题库61页
- hdu 3488(uva 1349)(KM)
- UVa 1411 Ants(KM)
- UVA 11383 KM性质
- uva 11383 Golden Tiger Claw km模版题 但为什么Wa了呀? (KM)
- uva 1045 - The Great Wall Game(KM)
- Uva live 4043 Ants( KM+简单的计算几何)
- UVA 11383 Golden Tiger Claw(KM算法)
- Uva 11383 Golden Tiger Claw(KM算法原理应用)
- uva 11383 Golden Tiger Claw (KM算法)
- UVA 11324 The Largest Clique (拆点+KM)
- 对互联网的几点思考
- 数组
- 最短子数组练习题 -- 算法小结
- 【树莓派】基本操作
- MyEclipse 10 代码提示
- Uva 10888 Warehouse(KM)
- 用随机数选人(几行没有任何技术含量的代码)
- VueJS(2)--创建工程
- BZOJ 1227: [SDOI2009]虔诚的墓主人 树状数组 组合数
- Java SE8 Lambda 基础入门---两个函数式接口:Predicate、Consumer
- Coreldraw修改平面图独到漂亮见解就在这里了
- 移动端车牌号识别技术介绍
- 配置JDK和Tomcat
- 机器翻译的评价标准BLEU(Evaluation criteria for machine translation)