ZOJ 1654 Place the Robots 二分图最大匹配

唉,又是神一样的建模,表示完全想不到。

题意是给你一块地,上面有空地,草地,障碍三种地形,然后让你在上面放机器人,机器人只能放在空地上。机器人会向上下左右四个方向发出攻击,机器人的攻击可以穿过草地但是无法穿过障碍。问你在不会是机器人相互攻击的前提下,最多能放多少个机器人。

我觉得大致的思路应该是这样的,首先会想当然的想到把能够相互攻击到的空地连边,然后求最大独立集,但最大独立集不好求,所以要想办法把它转化成最大匹配问题。

所以要想办法把空地变成边,首先一块空地肯定是有他的横坐标和纵坐标,可以表示成相交的两条在图上的路径的形式。并且有,如果两个空地在同一行或者同一列,如果中间没有障碍物相隔的话,那么肯定只能最多放一个机器人,就把他当成是一块空地来处理。这样我们就能把原来按照行和列进行分割和标号了。然后遍历所有行和列的交点,如果这个交点是空地的话,就建立一条从这一点行的编号到这一点列的编号的双向边,一个二分图就建立起来了。

二分图上的每一个点表示的是行上或者列上的一个区域,这个区域只能放置一个机器人,并且相连的两个点只能放一个机器人,这样就成功转化成求最大匹配的问题了。

另外,要注意这题的输出时非主流的Case :1,冒号在前面,一开始写成 Case 1:狂WA,真是囧

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>

using namespace std;

typedef long long LL;
const int maxn = 61;
const int maxk = maxn * maxn;
char buf[maxn][maxn];
int bx[maxk],by[maxk],n,m,cntx,cnty;
int xid[maxn][maxn],yid[maxn][maxn];
bool g[maxk][maxk],vis[maxk];

int dfs(int now) {
    for(int i = 1;i <= cnty;i++) if(g[now][i] && !vis[i]) {
        vis[i] = true;
        if(!by[i] || dfs(by[i])) {
            bx[now] = i; by[i] = now;
            return 1;
        }
    }
    return 0;
}

int solve() {
    int ret = 0;
    memset(bx,0,sizeof(bx));
    memset(by,0,sizeof(by));
    for(int i = 1;i <= cntx;i++) if(!bx[i]) {
        memset(vis,0,sizeof(vis));
        ret += dfs(i);
    }
    return ret;
}

int main() {
    int T; scanf("%d",&T);
    for(int kase = 1;kase <= T;kase++) {
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i++) scanf("%s",buf[i] + 1);
        //build-graph
        memset(xid,0,sizeof(xid));
        memset(yid,0,sizeof(yid));
        memset(g,0,sizeof(g));
        cntx = cnty = 0;
        for(int i = 1;i <= n;i++) {
            int flag = 0;
            for(int j = 1;j <= m;j++) {
                if(buf[i][j] == ‘o‘) {
                    if(flag == 0) cntx++,flag = 1;
                    xid[i][j] = cntx;
                } else if(buf[i][j] == ‘#‘) flag = 0;
            }
        }
        for(int j = 1;j <= m;j++) {
            int flag = 0;
            for(int i = 1;i <= n;i++) {
                if(buf[i][j] == ‘o‘) {
                    if(!flag) cnty++,flag = 1;
                    yid[i][j] = cnty;
                } else if(buf[i][j] == ‘#‘) flag = 0;
            }
        }
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= m;j++) if(xid[i][j] && yid[i][j]) {
                g[xid[i][j]][yid[i][j]] = true;
            }
        }
        int ans = solve();
        printf("Case :%d\n%d\n",kase,ans);
    }
    return 0;
}

ZOJ 1654 Place the Robots 二分图最大匹配

时间: 2024-08-25 07:37:24

ZOJ 1654 Place the Robots 二分图最大匹配的相关文章

ZOJ 1654 Place the Robots(最大匹配)

Robert is a famous engineer. One day he was given a task by his boss. The background of the task was the following: Given a map consisting of square blocks. There were three kinds of blocks: Wall, Grass, and Empty. His boss wanted to place as many ro

ZOJ 1654 - Place the Robots (二分图最大匹配)

题意:在一个m*n的地图上,有空地,草和墙,其中空地和草能穿透攻击光线,而墙不能.每个机器人能够上下左右攻击,问在地图上最多能放多少个不互相攻击的机器人. 这个题和HDU 1045 -  Fire Net很像.很容易联想到对每个点编号然后互相攻击的点连边再求图的最大独立集,但是这个题数据量太多,超时. 换个思路. 将每个机器人可以攻击到的区域在横和竖方向上分开,这样当横和竖攻击方向都确定时就可以确定一个机器人的放置位置,而在同一个横或竖的攻击区域内不可以再放置机器人. 这样我们把原图上的空地按照

UVa12549 Sentry Robots (二分图最大匹配,最小点集覆盖)

题意:http://vjudge.net/problem/UVA-12549 分析: 一个重要位置有(x,y)两个坐标,而要守住这个重要位置就相当于连一条x到y的弧.选了一个重要位置(x,y)放置机器人相当于选了所有x相同的弧或者y相同的弧.当所有的x或者y被选完的时候就完成了看守.具体来说二分图两列分别表示用编号代表行和列,从源点s向行连一条容量为1的弧,从列向汇点t连一条容量为1的弧,再对于每个重要位置(x,y),连一条从x指向y容量为1的弧,跑一次s-t的最大流,最大流出现是当源点s连出去

zoj - 2362 - Beloved Sons(二分图最大匹配)

题意:国王对其N个 (1 <= N <= 400)儿子各有一个喜欢度,有N个美女,N个儿子喜欢美女中的一些,国王的幸福感 = 对可以成婚的儿子的喜欢度 ^ 2 的和,问国王最幸福时,儿子的对象情况. 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2362 -->>男.女,很像二分图吧.. 要使平方和最大,可转化为要使和最大.. 将儿子按国王对他们的喜欢度从高到低排序,再依次进行匹配对象,因为在求增

ZOJ 1654 Place the Robots建图思维(分块思想)+二分匹配

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=654 AC一百道水题,不如AC一道难题来的舒服. 题意:一个n*m地图.*代表草地,#代表墙,o代表空地,要再图中的o处放机器人,机器人能够攻击(上下左右)4个方向,攻击范围无限长,并且机器人不能相互攻击,草地不能放置机器人,且机器人的攻击能够穿过草地,可是机器人的攻击不能穿过墙,比方 "   *o#o  "这一行就能够放两个机器人," o*oo

ZOJ 1654 Place the Robots (二分匹配 )

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=654 Robert is a famous engineer. One day he was given a task by his boss. The background of the task was the following: Given a map consisting of square blocks. There were three kinds of

ZOJ 1654 Place the Robots

题目大意: 在空地上放置尽可能多机器人,机器人朝上下左右4个方向发射子弹,子弹能穿过草地,但不能穿过墙, 两个机器人之间的子弹要保证互不干扰,求所能放置的机器人的最大个数 每个机器人所在的位置确定了,那么对应的横向和竖向子弹能到达的空地就全部被覆盖了 我们将横向所能连接在一块的空地区域标上同一个标号 比如o*o#o , 就可标号为10102因为1,3空地中间的草地不影响子弹的穿越 同理,我们将竖向的所能连接在一块的空地区域标上同一个标号 那么就可以建立一个横向到达竖向的二部图匹配 每次成功匹配一

ZOJ1654 Place the Robots(二分图最大匹配)

二分图最大匹配也叫二分图最大边独立数,就是二分图中最多能取出两两不相邻的边的数目. 如果题目没有墙,那就是一道经典的二分图最大匹配问题: 把地图上的行和列分别作为点的X部和Y部,地图上每一块空地看作边,边的两个端点就是它所在的x行y列.这样,求最大边独立集即可. 而这一题有墙,然后我不会了.. 其实这题的建模也是一样的,也是行和列作为点,空地作为边: 对于每一行把被墙分隔的每一块连通的区域缩成一点,列也一样: 行缩成的点作为X部,列Y部: 某行连通区域最多就只能在区域内某一块空地放机器人,列也是

ZOJ 1364 Machine Schedule(二分图最大匹配)

题意 机器调度问题 有两个机器A,B A有n种工作模式0...n-1 B有m种工作模式0...m-1 然后又k个任务要做 每个任务可以用A机器的模式i或b机器的模式j来完成 机器开始都处于模式0 每次换模式时都要重启 问完成所有任务机器至少重启多少次 最基础的二分图最大匹配问题 对于每个任务把i和j之间连一条边就可以构成一个二分图 那么每个任务都可以对应一条边 那么现在就是要找最少的点 使这些点能覆盖所有的边 即点覆盖数 又因为二分图的点覆盖数 = 匹配数 那么就是裸的求二分图最大匹配问题了 两