题目链接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1629 题目大意:有一块大小为n * m的地,其中一些位置是草地,一些位置是泥泞地,要用一些长无限制、宽为1的木板覆盖所有的泥泞地,但不能覆盖草地,木板可以重叠,问最少要多少块木板。 分析:最小点覆盖问题,匈牙利方法。 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define mp make_pair #define X first #define Y second #define MEMSET(a, b) memset(a, b, sizeof(a)) using namespace std; typedef unsigned int ui; typedef long long ll; typedef unsigned long long ull; typedef pair pii; typedef vector vi; typedef vi::iterator vi_it; typedef map mii; typedef priority_queue pqi; typedef priority_queue , greater > rpqi; typedef priority_queue pqp; typedef priority_queue , greater > rpqp; const int MAX_SIZE = 50 + 2; char str[MAX_SIZE][MAX_SIZE]; vi link[MAX_SIZE * MAX_SIZE / 2]; int hcnt[MAX_SIZE][MAX_SIZE]; int rsum, csum; bool vis[MAX_SIZE * MAX_SIZE / 2]; int pre[MAX_SIZE * MAX_SIZE / 2]; void input(int &r, int &c) { if (scanf("%d%d\n", &r, &c) != 2) { exit(EXIT_FAILURE); } for (int i = 0; i < r; ++i) { gets(str[i]); } } void build_graph(int r, int c) { int i, j; for (i = 0; i < r; ++i) { bool flag = false; for (j = 0; j < c; ++j) { if (str[i][j] == '.') { flag = false; } else { if (!flag) { flag = true; ++rsum; } hcnt[i][j] = rsum; } } } for (j = 0; j < c; ++j) { bool flag = false; for (i = 0; i < r; ++i) { if (str[i][j] == '.') { flag = false; } else { if (!flag) { flag = true; ++csum; } link[hcnt[i][j]].push_back(csum); } } } } int dfs(int u) { for (vi_it it = link[u].begin(); it != link[u].end(); ++it) { int v = *it; if (!vis[v]) { vis[v] = true; if (!pre[v] || dfs(pre[v])) { pre[v] = u; return 1; } } } return 0; } void solve() { int ret = 0; for (int i = 1; i <= rsum; ++i) { MEMSET(vis, 0); ret += dfs(i); } printf("%d\n", ret); } int main(int argc, char *argv[]) { // freopen("D:\\in.txt", "r", stdin); int r, c; input(r, c); build_graph(r, c); solve(); return 0; }