您的位置:首页 > 其它

HDU - 5556 Land of Farms 枚举 + 无向二分图最大独立集

2017-10-02 21:34 337 查看
题意:有一个农场大小为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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: