[ZOJ1002] Fire Net

Posted kma093

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZOJ1002] Fire Net相关的知识,希望对你有一定的参考价值。

题目链接:

走这里

题目分析:

联想到Asteroids这道题,将行和列分别作为二分图的两边的点,把点本身作为二分图的边去处理
那么这个题的限制条件打不穿的墙怎么处理呢,发现这样的话
\\[ ...X.. \\]
其实左边那段和右边那段在横着考虑的时候是互不影响的,不妨对行和列重新编号

技术图片

用一下某题解的剪枝讲解的图,样例第一个大概就是这个样子
然后对于每个空地的行编号和列编号连一条边,当空地已经被控制/放满了就是最终答案,跑最大匹配即可

代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
#define N (800 + 10)
using namespace std;
inline int read() 
    int cnt = 0, f = 1; char c = getchar();
    while (!isdigit(c)) if (c == '-') f = -f; c = getchar();
    while (isdigit(c)) cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();
    return cnt * f;

int n, cnt = 0, res = 0, l, r, ans;
char s[N][N];
int mapp[N][N], mapp2[N][N];
bool vis[N];
int nxt[N * 100], first[N * 100], to[N * 100], tot;
int match[N];
void add(int x, int y) nxt[++tot] = first[x], first[x] = tot, to[tot] = y;
void build_map() 
    for (register int i = 1; i <= n; ++i)
        for (register int j = 1; j <= n; ++j) 
            if (s[i][j] == 'X') 
                mapp[i][j] = 0;
                continue;
             else 
                if (s[i][j] == '.' && s[i][j - 1] == 'X') ++cnt;
                mapp[i][j] = cnt;
            
        
    l = cnt, cnt = 0;
    for (register int i = 1; i <= n; ++i)
        for (register int j = 1; j <= n; ++j) 
            if (s[j][i] == 'X') 
                mapp2[j][i] = 0;
                continue;
             else 
                if (s[j][i] == '.' && s[j - 1][i] == 'X') ++cnt;
                mapp2[j][i] = cnt;
            
        
    r = cnt, cnt = 0;
    for (register int i = 1; i <= n; ++i)
        for (register int j = 1; j <= n; ++j) 
            if (!mapp[i][j]) continue;
            add(mapp[i][j], mapp2[i][j]);
        


bool find (int u) 
    for (register int i = first[u]; i; i = nxt[i]) 
        int v = to[i];
        if (vis[v]) continue;
        else 
            vis[v] = true;
            if (match[v] == -1 || find(match[v])) 
                match[v] = u;
                return 1;
            
        
    
    return 0;

int hungary() 
    ans = 0;
    for (register int i = 1; i <= l; ++i) 
        memset(vis, 0, sizeof(vis));
        ans += find(i);
    
    return ans;

int main() 
//  freopen("1.in", "r", stdin);
  while (1) 
    n = read();
    if (!n) break;
    memset(first, 0, sizeof (first));
    memset(to, 0, sizeof(to));
    memset(nxt, 0, sizeof(nxt));
    tot = 0, l = 0, r = 0;
    for (register int i = 0; i <= n + 1; ++i)
        for (register int j = 0; j <= n + 1; ++j) s[i][j] = 'X';
    for (register int i = 1; i <= n; ++i) scanf("%s", s[i] + 1);
    for (register int i = 0; i <= n + 1; ++i) s[i][n + 1] = 'X';
    build_map();
    for (register int i = 1; i <= r; ++i) match[i] = -1;
    res = hungary();
    printf("%d\\n", res);
  
    return 0;

以上是关于[ZOJ1002] Fire Net的主要内容,如果未能解决你的问题,请参考以下文章

ZOJ1002 —— 深度优先搜索

ZOJ Problem Set - 3820 Building Fire Stations 树的直径 + 操作

ZOJ 1002 DFS

ZOJ 1002道题 程序问题

ZOJ问题(2010浙江大学研究生复试上机题目[找规律] hdoj 3788)

python fire库的使用