题目大意:给出一张地图,一个军队要征战整个土地。一块土地只能经过一次,有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