题目大意:给出一张地图,一个军队要征战整个土地。一块土地只能经过一次,有X的地方不能走,军队只会走R*C个格子,只会向下走,问最少需要多少军队能够征战所有的土地。
思路:这个是前几天考试的题,今天居然发现时BZ的原题,还好当时A掉了。。。
看到每个土地只能经过一次就想到了网络流什么的,再一想想好像是最小路径覆盖啊,然后拆点,建图,Hungary,二分图最小路径覆盖=点数-最大匹配,没了。。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 20010 using namespace std; int m,n,r,c; char src[200][200]; int num[200][200],cnt; int head[MAX],total; int _next[MAX],aim[MAX]; bool v[MAX]; int paired[MAX]; inline void Add(int x,int y) { _next[++total] = head[x]; aim[total] = y; head[x] = total; } bool Hungary(int x) { for(int i = head[x]; i; i = _next[i]) { if(!v[aim[i]]) { v[aim[i]] = true; if(!paired[aim[i]] || Hungary(paired[aim[i]])) { paired[aim[i]] = x; return true; } } } return false; } int main() { cin >> m >> n >> r >> c; for(int i = 1; i <= m; ++i) { scanf("%s",src[i] + 1); for(int j = 1; j <= n; ++j) if(src[i][j] == '.') num[i][j] = ++cnt; } for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) { if(!num[i][j]) continue; if(i + r > 0 && j + c > 0 && num[i + r][j + c]) Add(num[i][j],num[i + r][j + c] + cnt); if(i + c > 0 && j + r > 0 && num[i + c][j + r]) Add(num[i][j],num[i + c][j + r] + cnt); if(i + r > 0 && j - c > 0 && num[i + r][j - c]) Add(num[i][j],num[i + r][j - c] + cnt); if(i + c > 0 && j - r > 0 && num[i + c][j - r]) Add(num[i][j],num[i + c][j - r] + cnt); } int ans = 0; for(int i = 1; i <= cnt; ++i) { memset(v,false,sizeof(v)); ans += Hungary(i); } cout << cnt - ans << endl; return 0; }
原文地址:http://blog.csdn.net/jiangyuze831/article/details/40817821