容易想到将问题转化为求图的独立数问题 ,但求一般图的独立集是一个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. Python面试题库

    1.Python输出中文怎么解决 方法一:用encode和decode如:import os.pathimport xlrd,sys Filename=’/home/tom/Desktop/1234. ...

  2. centos 6.5 下用apache部署web 应用

    1. 修改/etc/httpd/conf/httpd.conf文件,添加一个virtualhost段,具体略.注意在段内配置NaveServer. 此文件全局也要配置一个NameServer(原因有待 ...

  3. poj 1011

    http://poj.org/problem?id=1011 这是一道POJ的搜索的题目,最开始确实难以理解,但做过一些搜索的题目后,也没那么难了. 大概题意就是,现在有N根木头,要拼成若干根木头,并 ...

  4. progressBar走马灯设置

    初始值Visible = false; 让progressBar1出现时: progressBar1.Visible = true; progressBar1.Style = ProgressBarS ...

  5. stream的seek方法实例

    using (FileStream outStream = new FileStream(@"D:\12.txt", FileMode.Open)) { using (FileSt ...

  6. suse linux 命令

    1.修改vftpd配置文件   vi /etc/vsftpd .conf                       #listen=YES   vi /etc/xinetd.d/vsftpd     ...

  7. WebFrom 的js日期控件

    1.WdatePicker.js /* * My97 DatePicker 4.7 Release * License: http://www.my97.net/dp/license.asp */ v ...

  8. xcode运行push通知总是提示输入用户名和密码

    xcode运行push通知总是提示输入用户名和密码,目前找到的解决方案是,  打开钥匙串,然后找到push证书下面的私有密钥,双击进入将访问控制设置为允许全部访问,即可.

  9. PHP如何判断远程图片文件是否存在

    <?php $url = 'http://www.nowamagic.net/images/test.jpg'; if( @fopen( $url, 'r' ) ) { echo 'File E ...

  10. ERROR ITMS-90032 “Invalid image path”

    在用 Application Loader上传spa 文件的时候出现这样的错误:ERROR ITMS-90032: "Invalid image path No image found at ...