http://poj.org/problem?id=2226 (题目链接)

题意

  给出一个只包含‘.’和‘*’的矩阵,用任意长度的宽为1的木板覆盖所有的‘*’而不覆盖‘.’,木板必须跟矩形的长或宽平行。问最少需要多少块木板。

Solution

  这道题的构图非常巧妙,堪称经典构图。对于每一个‘*’,要么就是被横的木板覆盖,要么就是被竖的木板覆盖,而木板的长度一定都是取到最长(因为题目没有说木板不能重叠,所以木板尽可能长不会使答案变大)。

  假设我们全部用横木板进行覆盖,那么可以很简单的统计出哪些地方用第几块木板覆盖;同样如果我们全部用竖的木板进行覆盖,也可以统计出哪些地方用第几块木板覆盖。所以我们最后要选择的木板就在这些木板中产生。 
   
  拿样例来举个例子: 
               横:1 0 2 0   竖:1 0 4 0 
                 0 3 3 3     0 3 4 5 
                 4 4 4 0     2 3 4 0 
                 0 0 5 0     0 0 4 0 
   
  所以现在问题就转化成了如何选取最少的木板,使所有的‘*’都被覆盖。这是不是很像二分图匹配中的最小点覆盖,可问题是我们怎么对它构图呢?

  对于每一个‘*’,都会有一个横木板和竖木板在这个位置相交。那么如果我们对于每一个‘*’给在这里相交的横木板和竖木板的编号连一条边,是不是每一条边都表示一个‘*’呢?答案是显然的。问题到这里也就迎刃而解了。最小点覆盖=最大匹配数,所以我们只需要连完边后跑匈牙利就可以了。

代码

// poj2226
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
inline LL getint() {
int f,x=0;char ch=getchar();
while (ch<='0' || ch>'9') {if (ch=='-') f=-1;else f=1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int maxn=1000;
struct edge {int to,next;}e[maxn*maxn];
int n,m,cnt,head[maxn],a[maxn][maxn],x[maxn][maxn],y[maxn][maxn],p[maxn],vis[maxn];
char s[maxn]; void insert(int u,int v) {
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
}
bool find(int x) {
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
vis[e[i].to]=1;
if (p[e[i].to]==0 || find(p[e[i].to])) {
p[e[i].to]=x;
return 1;
}
}
return 0;
}
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) {
scanf("%s",s);
for (int j=0;j<m;j++) {
if (s[j]=='*') a[i][j+1]=1;
else a[i][j+1]=0;
}
}
int xx=0,yy=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) if (a[i][j]>0) {
x[i][j]=++xx;
while (j<m && a[i][j+1]>0) {j++;x[i][j]=xx;}
}
for (int j=1;j<=m;j++)
for (int i=1;i<=n;i++) if (a[i][j]>0) {
y[i][j]=++yy;
while (i<n && a[i+1][j]>0) {i++;y[i][j]=yy;}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (a[i][j]>0) insert(x[i][j],y[i][j]);
int ans=0;
for (int i=1;i<=xx;i++) {
for (int j=1;j<=yy;j++) vis[j]=0;
if (find(i)) ans++;
}
printf("%d\n",ans);
return 0;
}

  

【poj2226】 Muddy Fields的更多相关文章

  1. 【POJ2226】Muddy Fields

    题目大意:给定一个 N*M 的图,图中有一些格子不能被任何东西覆盖,现有一些宽度为 1,长度任意的骨牌覆盖这些可以被覆盖的格子,骨牌之间可以重叠,求将所有可以被覆盖的格子覆盖所需的最小骨牌数是多少. ...

  2. 【poj3254】Corn Fields 状态压缩dp

    AC通道:http://vjudge.net/problem/POJ-3254 [题目大意] 农夫约翰购买了一处肥沃的矩形牧场,分成M*N(1<=M<=12; 1<=N<=12 ...

  3. 【POJ3254】Corn Fields 状压DP第一次

    !!!!!!! 第一次学状压DP,其实就是运用位运算来实现一些比较,挺神奇的.. 为什么要发“!!!”因为!x&y和!(x&y)..感受一下.. #include <iostre ...

  4. 【poj3254】 Corn Fields

    http://poj.org/problem?id=3254 (题目链接) 题意 给出一块n*m的田地,有些能够耕种,有些不能.要求将牛两两不相邻的放在田中,牛的个数至少为1个.问有多少种放法. So ...

  5. 【POJ3254】Corn Fields

    http://poj.org/problem?id=3254 题意:给你一块n*m(0<n,m<=12)的地图,其中有的方格是肥沃的(用1表示),有的方格是贫瘠的(用0表示).现在约翰要在 ...

  6. 【POJ3254】Corn Fields(状压DP)

    题意: 一个M x N矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案( ...

  7. 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP

    [BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M< ...

  8. 【BZOJ】1725: [Usaco2006 Nov]Corn Fields牧场的安排

    [算法]状压DP [题解]对于上一行的每个状态,每行进行DFS. #include<cstdio> #include<algorithm> #include<cstrin ...

  9. 【USACO 2006 November Gold】Corn Fields

    [题目链接] 点击打开链接 [算法] 状压DP [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 12 #def ...

随机推荐

  1. Android组件---四大布局的属性详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4372222.html Android常见布局有下面几种: LinearL ...

  2. 【markdown】markdown常用语法

    标题 用1~6个# 标题1 标题2 标题3 标题4 标题5 标题6 源码: # 标题1 ## 标题2 ### 标题3 #### 标题4 ##### 标题5 ###### 标题6 引用 引用使用 引用使 ...

  3. jquery给元素添加样式表的方法

    //1.获取和设置样式 $("#tow").attr("class")获取ID为tow的class属性 $("#two").attr(&qu ...

  4. AFN框架基本使用

    0.AFN框架基本使用 0.1 AFN内部结构 AFN结构体 - NSURLConnection + AFURLConnectionOperation(已经被废弃) + AFHTTPRequestOp ...

  5. SilverIight数据绑定实例

    前台Code <DataGrid Name="DataGrid1" AutoGenerateColumns="False" IsReadOnly=&quo ...

  6. [转]redis.conf的配置解析

    # redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位, # 通常的格式就是 1k 5gb 4m 等酱紫: # # 1k => 1000 bytes # 1kb ...

  7. Linux中查看各文件夹大小命令du -h --max-depth=1

    http://blog.csdn.net/ouyang_peng/article/details/10414499 du -h --max-depth=1  

  8. bootstrap modal的data-dismiss属性

    <button type="button" class="btn default" data-dismiss="modal">关 ...

  9. php基础03:数据类型

    <?php // day01:数据类型 //01.字符串 $x = "hello world"; echo $x; echo "<br>"; ...

  10. Android开发探秘之一:创建可以点击的Button

    感觉到自己有必要学习下手机开发方面的知识,不论是为了以后的工作需求还是目前的公司项目. 当然,任何新东西的开始,必然伴随着第一个HelloWorld,Android学习也不例外.既然才开始,我就不做过 ...