Battle shipsHDU - 5093

  题目大意:n*m的地图,*代表海洋,#代表冰山,o代表浮冰,海洋上可以放置船舰,但是每一行每一列只能有一个船舰(类似象棋的車),除非同行或者同列的船舰中间有冰山挡着,问最多能放多少个船舰?

  之前做过一个放置炮的,那时数据小直接暴力加搜索就A了,然而这题暴力搜索的话,直接了当的TLE,没办法只好去学新东西了。二分图这个概念只有在之前的题目中做过匈牙利的板子题,可是具体概念和思路并不了解,这题也正好提醒了我去深入了解。但最近需要做的事情较大,一直想整理的一些算法和模板总结也暂时拖一拖。

  回到这题,为什么可以用二分匹配做呢,首先如果没有障碍全是海的话,那就刚好是每一行每一列只能放一个,那我们分配的时候就是给每一行分配一列,这样一行一列刚好对应了放置的位置,而这个给每一行分配一列的过程刚好也可以用二分匹配实现。那么多了障碍之后,该如何处理呢,其实也就是一行分成多行,我们把相同行的统一编号化成一块区域,举个例子,比如2*6的地图

  ******

  ******

  之前每个点对行编号就是

  111111

  111111

  而多了障碍之后

  ***#**

  **#***

  这时的编号就是

  111022

  330444

  列的处理也是类似,列的编号就是

  123056

  120456

  有了编号之后,我们就可以根据共同点连边,像行编号为1的点和列编号为1,2,3的点有公共点,那么它们可以连边。上图每个行块可以连的列块就是

  1:1 2 3

  2:5,6

  3:1,2

  4:4,5,6

  这时我们就是尽可能多的给每一个行快分配一个列块,这样就可以得到最多的点,也就是最多能放置的数目。

 #include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
char s[][];
int x,y,xid[][],yid[][],cj[],vis[];
vector<int> vv[];
bool match(int u)
{
for(int i=;i<vv[u].size();i++)
{
int v=vv[u][i];
if(!vis[v])//这个列还没遍历过
{
vis[v]=;
if(!cj[v]||match(cj[v]))//这个列块还没分配给某个行块
{//或者它分配给的行块可以匹配其他列块
cj[v]=u;
return ;
}
}
}
return ;
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
scanf("%s",s[i]);
memset(xid,,sizeof(xid));
memset(yid,,sizeof(yid));
x=,y=;
for(int i=;i<n;i++)
{
int j=,is=;
while(j<m)
{
if(s[i][j]=='#')
is=;
while(j<m&&s[i][j]=='#')
j++;
if(s[i][j]=='*')
{
if(!is)
x++;
is=;
xid[i][j]=x;
}
j++;
}
}//给每个行块编号
for(int i=;i<m;i++)
{
int j=,is=;
while(j<n)
{
if(s[j][i]=='#')
is=;
while(i<n&&s[j][i]=='#')
j++;
if(s[j][i]=='*')
{
if(!is)
y++;
is=;
yid[j][i]=y;
}
j++;
}
}//给每个列块编号
for(int i=;i<=x;i++)
vv[i].clear();
for(int i=;i<n;i++)
for(int j=;j<m;j++)
if(s[i][j]=='*')//二分图加边
vv[xid[i][j]].push_back(yid[i][j]);
int ans=;
memset(cj,,sizeof(cj));
for(int i=;i<=x;i++)//匈牙利算法模板
{
memset(vis,,sizeof(vis));
ans+=match(i);
}
printf("%d\n",ans);
}
return ;
}

门泊东吴万里船

  感觉二分匹配难在怎么想到这个建边

最新文章

  1. DataGridView回车焦点横向移动
  2. CF#138 div 1 A. Bracket Sequence
  3. css pre标签
  4. {Latex}{Tabular}文本超出表格自动换行
  5. 设置Tomcat编码
  6. PHP __DIR__, __FILE__, __FUNCTION__, __CLASS__, __METHOD__, __LINE__, __NAMESPACE__
  7. codeforces 476C.Dreamoon and Sums 解题报告
  8. JavaScript学习之窗口
  9. ios ble 参考
  10. Microsoft2013校园招聘笔试题及解答
  11. java项目获取根路径(web项目和application项目的区分)
  12. Bootstrap table 行编辑导航
  13. Git学习指北
  14. Laravel数据库迁移
  15. matplotlib 3D数据-【老鱼学matplotlib】
  16. VMProtect1.63分析
  17. java集合类,详解
  18. xgboost安装
  19. 坐标的相对转换ClientToScreen与ScreenToClient
  20. 为何要对URL进行编码

热门文章

  1. Fiddler之常用操作(过滤器设置,代理设置,手机抓包设置,手机代理配置)
  2. Glide优化
  3. 5.Shell变量
  4. Java深入分析类与对象
  5. 精心整理的一些 Python 学习资料
  6. vue-cli实现原理
  7. Java: For循环那些事
  8. count(*),count(1),count(字段)
  9. 网络初级篇之VLAN(原理)
  10. PAT 1003.我要通过1