Battle ships HDU - 5093二分匹配

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

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

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 using namespace std;
 5 char s[52][52];
 6 int x,y,xid[52][52],yid[52][52],cj[520],vis[520];
 7 vector<int> vv[520];
 8 bool match(int u)
 9 {
10     for(int i=0;i<vv[u].size();i++)
11     {
12         int v=vv[u][i];
13         if(!vis[v])//这个列还没遍历过
14         {
15             vis[v]=1;
16             if(!cj[v]||match(cj[v]))//这个列块还没分配给某个行块
17             {//或者它分配给的行块可以匹配其他列块
18                 cj[v]=u;
19                 return 1;
20             }
21         }
22     }
23     return 0;
24 }
25 int main()
26 {
27     int t,n,m;
28     scanf("%d",&t);
29     while(t--)
30     {
31         scanf("%d%d",&n,&m);
32         for(int i=0;i<n;i++)
33             scanf("%s",s[i]);
34         memset(xid,0,sizeof(xid));
35         memset(yid,0,sizeof(yid));
36         x=0,y=0;
37         for(int i=0;i<n;i++)
38         {
39             int j=0,is=0;
40             while(j<m)
41             {
42                 if(s[i][j]==‘#‘)
43                     is=0;
44                 while(j<m&&s[i][j]==‘#‘)
45                     j++;
46                 if(s[i][j]==‘*‘)
47                 {
48                     if(!is)
49                         x++;
50                     is=1;
51                     xid[i][j]=x;
52                 }
53                 j++;
54             }
55         }//给每个行块编号
56         for(int i=0;i<m;i++)
57         {
58             int j=0,is=0;
59             while(j<n)
60             {
61                 if(s[j][i]==‘#‘)
62                     is=0;
63                 while(i<n&&s[j][i]==‘#‘)
64                     j++;
65                 if(s[j][i]==‘*‘)
66                 {
67                     if(!is)
68                         y++;
69                     is=1;
70                     yid[j][i]=y;
71                 }
72                 j++;
73             }
74         }//给每个列块编号
75         for(int i=0;i<=x;i++)
76             vv[i].clear();
77         for(int i=0;i<n;i++)
78             for(int j=0;j<m;j++)
79                 if(s[i][j]==‘*‘)//二分图加边
80                     vv[xid[i][j]].push_back(yid[i][j]);
81         int ans=0;
82         memset(cj,0,sizeof(cj));
83         for(int i=1;i<=x;i++)//匈牙利算法模板
84         {
85             memset(vis,0,sizeof(vis));
86             ans+=match(i);
87         }
88         printf("%d\n",ans);
89     }
90     return 0;
91 } 

门泊东吴万里船

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

原文地址:https://www.cnblogs.com/LMCC1108/p/10642199.html

时间: 2024-11-06 09:54:15

Battle ships HDU - 5093二分匹配的相关文章

hdu 5093 二分匹配

/* 题意:给你一些冰岛.公共海域和浮冰,冰岛可以隔开两个公共海域,浮冰无影响 求选尽可能多的选一些公共海域点每行每列仅能选一个. 限制条件:冰山可以隔开这个限制条件.即*#*可以选两个 预处理: ***** **#*# ***** 可以按行转化 ***** **#oo ooo*# ***** 按列转化 ***o**o **ooooo oooo*oo **o**o* 因为每行每列顶多可以增加50 所以总共最多2500*2500的矩阵 然后直接二分匹配即可 */ #include<stdio.h>

Hdu 2389 二分匹配

题目链接 Rain on your Parade Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 655350/165535 K (Java/Others)Total Submission(s): 2644    Accepted Submission(s): 823 Problem Description You’re giving a party in the garden of your villa by the sea. T

HDU 5093 二分最大匹配

Battle ships Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 394    Accepted Submission(s): 178 Problem Description Dear contestant, now you are an excellent navy commander, who is responsible o

hdu 4169 二分匹配最大独立集 ***

题意:有水平N张牌,竖直M张牌,同一方向的牌不会相交.水平的和垂直的可能会相交,求最少踢出去几张牌使剩下的牌都不相交. 二分匹配 最小点覆盖=最大匹配. 链接:点我 坐标点作为匹配的端点 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #incl

hdu 4685 二分匹配+强连通分量

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 题解: 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<vector> 5 #include<stack> 6 #include<algorithm> 7 using namespace std; 8 9 const int maxn =

HDU 3729 二分匹配匈牙利算法

I'm Telling the Truth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1482    Accepted Submission(s): 740 Problem Description After this year’s college-entrance exam, the teacher did a survey in

H - Prince and Princess - HDU 4685(二分匹配+强连通分量)

题意:有N个王子M个公主,王子喜欢一些公主,而且只能是王子喜欢的人,他们才可以结婚,现在让他们尽可能多的结婚的前提下找出来每个王子都可以和谁结婚. 分析:先求出来他们的最大匹配,因为给的数据未必是完备匹配,所以需要添加一些点使他们成为完备匹配才能求出来的环是完整的,比如第二组数据: 1 2   2 1 2 如果不添加虚拟点做成匹配,只会匹配成功一个,这样就找不出来环了,所以需要添加虚拟的王子和公主,虚拟的王子喜欢所有的公主,虚拟的公主被所有的王子喜欢,注意都是王子喜欢公主的,公主没有选择喜欢的权

HDU 5090 二分匹配

Game with Pearls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 172    Accepted Submission(s): 103 Problem Description Tom and Jerry are playing a game with tubes and pearls. The rule of the g

Treasure Hunting (hdu 3468 二分匹配+bfs最短路径)

Treasure Hunting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 1509    Accepted Submission(s): 393 Problem Description Do you like treasure hunting? Today, with one of his friend, iSea is on