容易想到将问题转化为求图的独立数问题 ,但求一般图的独立集是一个NPC问题,需要一些转化。

状态压缩,枚举每个上古农场是否选择,然后将剩下的新农场根据i + j奇偶性分为x , y集。

结果为 max(tot  + nx + ny - 二分图匹配数)

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<utility>
using namespace std;
typedef long long LL;
const int N = 150, INF = 0x3F3F3F3F; int mp[15][15]; int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; int cx[N], cy[N];//匹配结果
int nx, ny;//x,y集合元素个数
bool inx[N], iny[N]; bool used[N];
bool nop[15][15]; //存x到y集合的有向图
struct Node{
int to,next;
}edge[1000];
int head[N],tot; bool dfs(int u){
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(!used[v]){
used[v] = true;
if(cy[v] == -1 || dfs(cy[v])){
cx[u] = v;
cy[v] = u;
return true;
}
}
}
return false;
} int Hungary(){
int ans = 0;
memset(cx, -1, sizeof(cx));
memset(cy, -1, sizeof(cy));
for(int i = 0; i < nx; i++){
if(cx[i] == -1){
memset(used, 0, sizeof(used));
if(dfs(i)){
ans++;
}
}
}
return ans;
} void init(){
memset(head, -1, sizeof(head));
tot = 0;
}
void add(int u, int to){
edge[tot].to=to;
edge[tot].next=head[u];
head[u]=tot++;
} bool check(int n, int m, int st){
memset(nop, 0, sizeof(nop));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(st & (1 << mp[i][j])){
for(int k = 0; k < 4; k++){
int u = i + dir[k][0];
int v = j + dir[k][1];
if((mp[u][v] != -1) && (mp[i][j] != mp[u][v]) && (st & (1 << mp[u][v]))){
return false;
}
nop[u][v] = 1;
}
}
}
}
return true; }
char str[N];
int main(){
int t, n, m;
cin>>t;
int vis[N];
for(int cas = 1; cas <= t; cas++){
scanf("%d %d", &n, &m);
int ans = 0;
memset(mp, -1, sizeof(mp));
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++){
scanf("%s", str + 1);
for(int j = 1; j <= m; j++){
if(str[j] == '.'){
mp[i][j] = 10;
}else{
mp[i][j] = str[j] - '0';
vis[str[j] - '0'] = 1;
}
}
}
int cnt = 0;
for(int i = 0; i < 10; i++){
if(vis[i]){
vis[i] = cnt++;
}
} for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(mp[i][j] < 10){
mp[i][j] = vis[mp[i][j]];
}
}
} for(int st = 0; st < (1 << cnt); st++){
int tot = 0;
int tp = st;
while(tp){
tot += tp & 1;
tp >>= 1;
} if(!check(n, m, st)){
continue;
}
init();
nx = 0;
ny = 0;
memset(inx, 0, sizeof(inx));
memset(iny, 0, sizeof(iny));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(mp[i][j] < 10){
nop[i][j] = 1;
} if((i + j) % 2){
if(mp[i][j] == 10 && !nop[i][j]){
iny[(i - 1) *m + j - 1] = 1;
}
} if((i + j) % 2 == 0){
if(mp[i][j] == 10 && !nop[i][j]){
inx[(i - 1) *m + j - 1] = 1;
for(int k = 0; k < 4; k++){
int u = i + dir[k][0];
int v = j + dir[k][1];
if(mp[u][v] == 10 && !nop[u][v]){
add((i - 1) *m + j - 1, (u - 1) *m + v - 1);
} } } } }
}
for(int i = 0; i < n * m; i++){
if(inx[i]){
tot++;
nx = i + 1;
}
if(iny[i]){
tot++;
ny = i + 1;
}
}
ans = max(ans, tot - Hungary());
} printf("Case #%d: %d\n", cas, ans);
} return 0;
}

  

HDU5556 Land of Farms(二分图 2015 合肥区域赛)的更多相关文章

  1. HDU5558 Alice's Classified Message(合肥区域赛 后缀数组)

    当初合肥区域赛的题(现场赛改了数据范围就暴力过了),可惜当初后缀数组算法的名字都没听过,现在重做下. i从1到n - 1,每次枚举rank[i]附近的排名,并记录当起点小于i时的LCP(rank[i] ...

  2. hdu5556 Land of Farms

    我对于题目的一种理解 改造农场 1.建新农场 在空的点选 2.重建旧农场 选一个点属于这个农场的地方都要选 最后的农场都不能相连 所以枚举旧农场的个数并进行二分图匹配 #include<bits ...

  3. 2015北京区域赛 Xiongnu's Land

    Wei Qing (died 106 BC) was a military general of the Western Han dynasty whose campaigns against the ...

  4. Travel(HDU 5441 2015长春区域赛 带权并查集)

    Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Su ...

  5. hdu 5493 (2015合肥网赛) Queue

    题目;http://acm.hdu.edu.cn/showproblem.php?pid=5493 题目大意,t组数据,n个人,n行每行分别是人的身高和这个人的左边或右边比他高的人的个数,输出符合条件 ...

  6. hdu 5491(2015合肥网赛)The Next

    题目;http://acm.hdu.edu.cn/showproblem.php?pid=5491 题意就是,T组测试数据.然后L,S1,S2.L的二进制中有x个1,x满足  S1<=x< ...

  7. HDU 5552 Bus Routes(2015合肥现场赛A,计数,分治NTT)

    题意  给定n个点,任意两点之间可以不连边也可以连边.如果连边的话可以染上m种颜色. 求最后形成的图,是一个带环连通图的方案数. 首先答案是n个点的图减去n个点能形成的树. n个点能形成的树的方案数比 ...

  8. ACM学习历程—HDU5490 Simple Matrix (数学 && 逆元 && 快速幂) (2015合肥网赛07)

    Problem Description As we know, sequence in the form of an=a1+(n−1)d is called arithmetic progressio ...

  9. 2015合肥网络赛 HDU 5489 Removed Interval LIS+线段树(树状数组)

    HDU 5489 Removed Interval 题意: 求序列中切掉连续的L长度后的最长上升序列 思路: 从前到后求一遍LIS,从后往前求一遍LDS,然后枚举切开的位置i,用线段树维护区间最大值, ...

随机推荐

  1. [翻译]opengl扩展教程1

    [翻译]opengl扩展教程1 原文地址https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/extensions.php [翻译]ope ...

  2. String和StringBuffer的转换

    从String到StringBuffer: StringBuffer sb = New StringBuffer("abcd");从StringBuffer到String: Str ...

  3. phpcms新闻轮播图实现

    首页如果有新闻的轮播图,点击图片可以进入相关的新闻.因为已经使用外部js轮播插件,所以想不修改插件进行轮播 我用的js插件是yx-rotaion插件,配合phpcms的get工具箱对新闻进行读取并抽取 ...

  4. ubuntu 16.04 apt-get error: in the drive /media/cdrom and press

    If you have an internet connection, you can safely comment out the line starting with deb cdrom: ... ...

  5. 【Kubernetes】两篇文章 搞懂 K8s 的 fannel 网络原理

    近期公司的flannel网络很不稳定,花时间研究了下并且保证云端自动部署的网络能够正常work. 1.网络拓扑 拓扑如下:(点开看大图)  容器网卡通过docker0桥接到flannel0网卡,而每个 ...

  6. meeting room I & II

    Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si ...

  7. Word Search I & II

    Word Search I Given a 2D board and a word, find if the word exists in the grid. The word can be cons ...

  8. python之打包相关

    打包手册:https://python-packaging-user-guide.readthedocs.org/en/latest/installing.html#installing-from-a ...

  9. mybaits in

    mybatis中的in: <select id="getByInventoryIds" resultMap="beanMap"> SELECT * ...

  10. bccomp比较大小注意

    2015年12月15日 14:18:56 星期二 echo bccomp('1', '1.01', 2); // -1 echo bccomp('1', '1.01', 3); // -1 echo ...