zoukankan      html  css  js  c++  java
  • [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
    ", res);
      }
    	return 0;
    }
    
    
  • 相关阅读:
    mongodb性能测试:long时间戳与string格式时间
    .netcore mongodb 分页+模糊查询+多条件查询
    .netcore 图片处理
    ELEMENT-UI 封装el-table 局部刷新row
    vue-upload 封装组件-上传组件
    vue实现v-model父子组件间的双向通信
    cc.AudioSource
    Chrome插件:本地程序实现验证码破解(浏览器与本地进程通信)
    Chrome插件:微信公众号自动登录(chrome.extension)
    Chrome插件:浏览器后台与页面间通信
  • 原文地址:https://www.cnblogs.com/kma093/p/11518284.html
Copyright © 2011-2022 走看看