ZOJ1654.Place the Robots放置机器人——二部图最大匹配(hungary算法)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=654

题目描述:

Robert 是一个著名的工程师。一天,他的老板给他分配了一个任务。任务的背景是:给定一

个m×n 大小的地图,地图由方格组成,在地图中有3 种方格-墙、草地和空地,他的老板希望

能在地图中放置尽可能多的机器人。每个机器人都配备了激光枪,可以同时向四个方向(上、下、

左、右)开枪。机器人一直待在最初始放置的方格处,不可移动,然后一直朝四个方向开枪。激

光枪发射出的激光可以穿透草地,但不能穿透墙壁。机器人只能放置在空地。当然,老板不希望

机器人互相攻击,也就是说,两个机器人不能放在同一行(水平或垂直),除非他们之间有一堵墙

格开。

给定一张地图,你的程序需要输出在该地图中可以放置的机器人的最大数目。

思路:

以样例解释

在问题的原型中,草地,墙这些信息不是本题所关心的,本题关心的只是空地和空地之间的联系。因此,很自然想到了下面这种简单的模型:以空地为顶点,在有冲突的空地间连边。

把所有的空地用数字标明,得到a图:

把所有有冲突的空地间用边连接后得到图(b):

于是,问题转化为求图的最大独立集问题:求最大顶点集合,集合中所有顶点互不连接(即互不冲突)。但是最大点独立集问题是一个NP 问题,没有有效的算法能求解。

————————————————————————————————————————————————————————————————————————

将每一行被墙隔开、且包含空地的连续区域称作“块”。显然,在一个块之中,最多只能放一个机器人。把这些块编上号,如图7.25(a)所示。需要说明的是,最后一行,即第4 行有两个空地,但这两个空地之间没有墙壁,只有草地,所以这两个空地应该属于同一“块”。同样,把竖直方向的块也编上号,如图7.25(b)所示。

把每个横向块看作二部图中顶点集合X 中的顶点,竖向块看作集合Y 中的顶点,若两个块有公共的空地(注意,每两个块最多有一个公共空地),则在它们之间连边。例如,横向块2 和竖向块1 有公共的空地,即(2, 0),于是在X 集合中的顶点2 和Y 集合中的顶点1 之间有一条边。这样,问题转化成一个二部图,如图7.25(c)所示。由于每条边表示一个空地(即一个横向块和一个竖向块的公共空地),有冲突的空地之间必有公共顶点。例如边(x1, y1)表示空地(0, 0)、边(x2, y1)表示空地(2, 0),在这两个空地上不能同时放置机器人。所以问题转化为在二部图中找没有公共顶点的最大边集,这就是最大匹配问题。

以上面给的样例的构造结果:

匈牙利算法 O( |E| sqrt(|V|) )

0MS 372KB

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
const int MAXN=2550;
using namespace std;
int n,m;
int nx,ny;//水平方向上块的个数,垂直方向上块的个数
char pic[55][55];//地图
int xs[55][55],ys[55][55];//水平方向上块的编号,垂直方向上块的编号
vector<int> g[MAXN];//g[i]表示与左边点i相连的右边的点
int from[MAXN];//from[y]表示与Yi匹配的X顶点   // cy数组
int tot;//最大匹配数
bool use[MAXN];//
int flag;
bool match(int x){
    for(int i=0;i<g[x].size();++i){
        if(!use[g[x][i]]){
            use[g[x][i]]=true;
            if(from[g[x][i]]==-1||match(from[g[x][i]])){
                from[g[x][i]]=x;
                return true;
            }
        }
    }
    return false;
}
int hungary(){
    tot=0;
    memset(from,255,sizeof(from));
    for(int i=1;i<=nx;++i){
        memset(use,0,sizeof(use));
        if(match(i))
            ++tot;
    }
    return tot;
}
int main()
{
    int T;
    cin>>T;
    for(int cas=1;cas<=T;++cas){
        printf("Case :%d\n",cas);
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;++i) scanf("%s",pic[i]);
        nx=ny=0;
        memset(xs,0,sizeof(xs));
        memset(ys,0,sizeof(ys));
        for(int i=0;i<n;++i){
            flag=0;
            for(int j=0;j<m;++j){
                if(pic[i][j]==‘o‘){
                    if(!flag) ++nx;
                    flag=1;
                    xs[i][j]=nx;
                }else if(pic[i][j]==‘#‘) flag=0;
            }
        }
        for(int j=0;j<m;++j){
            flag=0;
            for(int i=0;i<n;++i){
                if(pic[i][j]==‘o‘){
                    if(!flag) ++ny;
                    flag=1;
                    ys[i][j]=ny;
                }else if(pic[i][j]==‘#‘) flag=0;
            }
        }
        for(int i=1;i<=nx;++i) g[i].clear();
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                if(xs[i][j]&&ys[i][j])
                    g[xs[i][j]].push_back(ys[i][j]);
            }
        }
        printf("%d\n",hungary());
    }
    return 0;
}
时间: 2024-11-09 03:17:11

ZOJ1654.Place the Robots放置机器人——二部图最大匹配(hungary算法)的相关文章

zoj1654 Place the Robots

题目描述: Robert 是一个著名的工程师.一天,他的老板给他分配了一个任务.任务的背景是:给定一 个m×n 大小的地图,地图由方格组成,在地图中有3 种方格-墙.草地和空地,他的老板希望 能在地图中放置尽可能多的机器人.每个机器人都配备了激光枪,可以同时向四个方向(上.下. 左.右)开枪.机器人一直待在最初始放置的方格处,不可移动,然后一直朝四个方向开枪.激 光枪发射出的激光可以穿透草地,但不能穿透墙壁.机器人只能放置在空地.当然,老板不希望 机器人互相攻击,也就是说,两个机器人不能放在同一

POJ1274:The Perfect Stall(二分图最大匹配 匈牙利算法)

The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17895   Accepted: 8143 Description Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering pr

Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)

解题报告 二分图第一题. 题目描述: 为了参加即将召开的会议,A国派出M位代表,B国派出N位代表,(N,M<=1000) 会议召开前,选出K队代表,每对代表必须一个是A国的,一个是B国的; 要求每一个代表要与另一方的一个代表联系,除了可以直接联系,也可以电话联系,求电话联系最少 思路: 电话联系最少就要使直接联系最大,又是一一匹配关系,就是二分图的最大匹配. 下面是匈牙利算法. #include <cstdio> #include <cstring> #include <

UESTC 919 SOUND OF DESTINY --二分图最大匹配+匈牙利算法

二分图最大匹配的匈牙利算法模板题. 由题目易知,需求二分图的最大匹配数,采取匈牙利算法,并采用邻接表来存储边,用邻接矩阵会超时,因为邻接表复杂度O(nm),而邻接矩阵最坏情况下复杂度可达O(n^3). 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> u

SPOJ 4206 Fast Maximum Matching (二分图最大匹配 Hopcroft-Carp 算法 模板)

题目大意: 有n1头公牛和n2头母牛,给出公母之间的m对配对关系,求最大匹配数.数据范围:  1 <= n1, n2 <= 50000, m <= 150000 算法讨论: 第一反应KM直接上,第二反应,KM是O(N^2 * M)的,会T成狗. 第二反应,看看大家是怎么做的.后来发现了一个名字叫 Hopcroft-Carp的二分图最大匹配的算法.可以在O(sqrt(n) * m)的时间内解决二分图的最大匹配问题.非常适合大数据的二分图匹配.所以就学习了一下. 我们知道,普通的匈牙利慢的原

二分图的最大匹配——匈牙利算法

一.前人种树 博客:趣写算法系列--匈牙利算法 博客:二分图最大匹配 博客:二分图的最大匹配--匈牙利算法 二.题目讲解 博客:POJ1274:The Perfect Stall(二分图最大匹配 匈牙利算法)

hdu 2063 过山车 (最大匹配 匈牙利算法模板)

匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2063 题目大意: 中文题目,点进去马上知道. 解题思路: 这道题目就是求最大匹配数目,直接套用匈牙利算法模板,这个算法大概原则就是:有机会上,没有机会创造机会也要上. 代码: 1 #i

最大匹配分词算法

全文检索有两个重要的过程: 1分词   2倒排索引 我们先看分词算法 目前对中文分词有两个方向,其中一个是利用概率的思想对文章分词. 也就是如果两个字,一起出现的频率很高的话,我们可以假设这两个字是一个词.这里可以用一个公式衡量:M(A,B)=P(AB)/P(A)P(B),其中 A表示一个字,B表示一个字,P(AB)表示AB相邻出现的概率,P(A)表示A在这篇文章中的频度,P(B)表示B在这篇文章中的频度.用概率分词的好 处是不需要借助词典的帮助,坏处是算法比较麻烦,效率不高,也存在一定的出错率

求无权图的最大匹配---匈牙利算法

匈牙利算法 匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名,,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. [先介绍几个概念] 匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点.例如,图3.图4 中红色的边就是图 2 的匹配. 我们定义匹配点.匹配边.未匹配点.非匹配边,它们的含义非常显然.例如图 3中 1.4.5.7为匹配点,其他顶点为未匹配点:1-5.4-7为匹配边,其他边为