HDU

来源:互联网 发布:淘宝 小电影 编辑:程序博客网 时间:2024/06/07 09:49

题意:有一个农场大小为n*m  里面有一些古老的农田,你现在需要新建一些农田,要求新建的农田之间不能相连,古老的农田不可拆分,如果你选择了一块土地(原为古老的农田)建立新农田则该新农田需要把一整块连通的古老的农田全部包含。问最多能新建多少个农田。

思路:由于古老的农田只有10个,因此我们可以枚举选哪几个古老的农田,然后对于剩下的空地,相邻空地之间建边,求一个二分图的最大独立集就是剩下的空地中最多能新建的农田数,再加上选出来的古老农田数就行了。

注意选出来的古老农田四周的空地不能建图,以避免新农田之间相连。

代码:

#include<bits/stdc++.h>using namespace std;const int MAXN = 110;int N, M;int mp[15][15];int go[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};int uN, vN;bool g[MAXN][MAXN];int linker[MAXN];bool used[MAXN];bool dfs(int u){    for(int v = 1; v <= vN; v++)    if(g[u][v] && !used[v])    {        used[v] = 1;        if(linker[v] == -1 || dfs(linker[v]))        {            linker[v] = u;            return 1;        }    }    return 0;}int hungary(){    int res = 0;    memset(linker, -1, sizeof(linker));    for(int u = 1; u <= uN; u++)    {        memset(used, 0, sizeof used);        if(dfs(u)) res++;    }    return res;}bool check(int status){int r, c;for(int i = 1; i <= N; i++){for(int j = 1; j <= M; j++){if(mp[i][j] == '.') continue;if(!(status >> mp[i][j] & 1)) continue;for(int k = 0; k < 4; k++){r = i + go[k][0];c = j + go[k][1];if(r < 1 || c < 1 || r > N || c > M) continue;if(mp[r][c] == '.' || mp[r][c] == mp[i][j]) continue;if(status >> mp[r][c] & 1) return 1;}}}return 0;}bool judge(int i, int j, int status){int r, c;for(int k = 0; k < 4; k++){r = i + go[k][0];c = j + go[k][1];if(r < 1 || c < 1 || r > N || c > M) continue;if(mp[r][c] == '.') continue;if(status >> mp[r][c] & 1) return 1;}return 0;}int solve(int status){int r, c, cnt = 0;uN = vN = N * M;memset(g, 0, sizeof(g));for(int i = 1; i <= N; i++){for(int j = 1; j <= M; j++){if(mp[i][j] != '.') continue;if(judge(i, j, status)) continue;cnt++;if((i + j) & 1) continue;for(int k = 0; k < 4; k++){r = i + go[k][0];c = j + go[k][1];if(r < 1 || c < 1 || r > N || c > M) continue;if(mp[r][c] != '.' || judge(r, c, status)) continue;g[(i - 1) * M + j][(r - 1) * M + c] = 1;}}}return cnt - hungary();}int bk[300], tid;int main(){//cout << (char)9;    int T, r, c, x, y;    cin >> T;    for(int kase = 1; kase <= T; kase++)    {    tid = 0;    memset(bk, -1, sizeof(bk));        scanf("%d %d", &N, &M);        for(int i = 1; i <= N; i++)        {        for(int j = 1; j <= M; j++)        {        scanf(" %c", &mp[i][j]);        if(mp[i][j] == '.') continue;        if(bk[mp[i][j]] == -1) bk[mp[i][j]] = tid++;        mp[i][j] = bk[mp[i][j]];}}int up = 1 << tid, ans = 0;       for(int i = 0; i < up; i++)       {       if(check(i)) continue;       ans = max(ans, solve(i) + __builtin_popcount(i));}        printf("Case #%d: %d\n", kase, ans);    }}


原创粉丝点击