HDOJ 5093 Battle ships 二分图匹配

二分图匹配:

分别按行和列把图展开,hungary二分图匹配。。。。

样例:
4 4
*ooo
o###
**#*
ooo*
按行展开。。。。
*ooo
o#oo
oo#o
ooo#
**#o
ooo*
ooo*
再按列展开。。。
7 * 8
*ooooooo
oooooooo
oooooooo
oooooooo
*o*ooooo
ooooooo*
ooooooo*  匹配结果3

Battle ships

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 106    Accepted Submission(s): 53

Problem Description

Dear contestant, now you are an excellent navy commander, who is responsible of a tough mission currently.

Your fleet unfortunately encountered an enemy fleet near the South Pole where the geographical conditions are negative for both sides. The floating ice and iceberg blocks battleships move which leads to this unexpected engagement highly dangerous, unpredictable
and incontrollable.

But, fortunately, as an experienced navy commander, you are able to take opportunity to embattle the ships to maximize the utility of cannons on the battleships before the engagement.

The target is, arrange as many battleships as you can in the map. However, there are three rules so that you cannot do that arbitrary:

A battleship cannot lay on floating ice

A battleship cannot be placed on an iceberg

Two battleships cannot be arranged in the same row or column, unless one or more icebergs are in the middle of them.

Input

There is only one integer T (0<T<12) at the beginning line, which means following T test cases.

For each test case, two integers m and n (1 <= m, n <= 50) are at the first line, represents the number of rows and columns of the battlefield map respectively. Following m lines contains n characters iteratively, each character belongs to one of ‘#’, ‘*’,
‘o’, that symbolize iceberg, ordinary sea and floating ice.

Output

For each case, output just one line, contains a single integer which represents the maximal possible number of battleships can be arranged.

Sample Input

2
4 4
*ooo
o###
**#*
ooo*
4 4
#***
*#**
**#*
ooo#

Sample Output

3
5

Source

2014上海全国邀请赛——题目重现(感谢上海大学提供题目)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=2600;

char mp[55][55];
char hang[maxn][maxn];
char lie[maxn][maxn];

int n,m;
int nn,mm;

void getHang()
{
  nn=0;
  for(int i=0;i<n;i++)
    {
      for(int j=0;j<m;j++)
        {
          if(mp[i][j]=='o')
            {
              hang[nn][j]='o';
            }
          else if(mp[i][j]=='*')
            {
              hang[nn][j]='*';
            }
          else if(mp[i][j]=='#')
            {
              hang[nn][j]='#';
              for(int k=j+1;k<m;k++)
                {
                  hang[nn][k]='o';
                }
              if(j!=m-1)
                {
                  nn++;
                  for(int k=0;k<=j;k++)
                    {
                      hang[nn][k]='o';
                    }
                }
            }
        }
      nn++;
    }
  /*********************debug***********************
  cout<<" debug hang \n";
  for(int i=0;i<nn;i++)
    {
      printf("%s\n",hang[i]);
    }
  *********************debug***********************/
}

void getLie()
{
  mm=0;
  for(int i=0;i<m;i++)
    {
      for(int j=0;j<nn;j++)
        {
          if(hang[j][i]=='*')
            {
              lie[j][mm]='*';
            }
          else if(hang[j][i]=='o')
            {
              lie[j][mm]='o';
            }
          else if(hang[j][i]=='#')
            {
              for(int k=j;k<nn;k++)
                {
                  lie[k][mm]='o';
                }
              if(j!=nn-1)
                {
                  mm++;
                  for(int k=0;k<=j;k++)
                    {
                      lie[k][mm]='o';
                    }
                }
            }
        }
      mm++;
    }
  /**************debug lie*******************
  cout<<"debug lie\n";
  cout<<nn<<" * "<<mm<<endl;
  for(int i=0;i<nn;i++)
    {
      for(int j=0;j<mm;j++)
        {
          printf("%c",lie[i][j]);
          if(j==mm-1) putchar(10);
        }
    }
  **************debug lie*******************/
}

struct Edge
{
  int to,next;
}edge[maxn*maxn];

int Adj[maxn],Size;

void init()
{
  memset(Adj,-1,sizeof(Adj)); Size=0;
}

void add_edge(int u,int v)
{
  edge[Size].to=v; edge[Size].next=Adj[u]; Adj[u]=Size++;
}

int linker[maxn];
bool used[maxn];

bool dfs(int u)
{
  for(int i=Adj[u];~i;i=edge[i].next)
    {
      int v=edge[i].to;
      if(!used[v])
        {
          used[v]=true;
          if(linker[v]==-1||dfs(linker[v]))
            {
              linker[v]=u;
              return true;
            }
        }
    }
  return false;
}

int hungary()
{
  int res=0;
  memset(linker,-1,sizeof(linker));
  for(int u=0;u<nn;u++)
    {
      memset(used,false,sizeof(used));
      if(dfs(u)) res++;
    }
  return res;
}

int main()
{
  int T_T;
  scanf("%d",&T_T);
  while(T_T--)
    {
      memset(mp,0,sizeof(mp));
      memset(hang,0,sizeof(hang));
      memset(lie,0,sizeof(lie));
      init();

      scanf("%d%d",&n,&m);
      for(int i=0;i<n;i++)
          scanf("%s",mp[i]);

      getHang();
      getLie();

      /// build graph

      for(int i=0;i<nn;i++)
        {
          for(int j=0;j<mm;j++)
            {
              if(lie[i][j]=='*')
                {
                  add_edge(i,j);
                }
            }
        }

      printf("%d\n",hungary());
    }
  return 0;
}
时间: 2024-10-11 11:01:31

HDOJ 5093 Battle ships 二分图匹配的相关文章

hdu 5093 Battle ships 二分图匹配

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5093 一开始就往贪心的方向想了结果wa全场 这种矩阵形式的图一般要联想到行和列构成了二分图 然后实质就是求一个最大匹配 中间的冰山实际上就是把一行或一列切成多个顶点而已 所以一开始预处理一下 然后就可以套用模板 #include <cstring> #include <cstdlib> #include <cstring> #include <cmath> #i

hdoj 5093 Battle ships 【二分图最大匹配】

题目:hdoj 5093 Battle ships 题意:给你一个n*m的图,图中有冰山 '# ',浮冰 'o' 以及普通海 ' * ',现在要在海中布置尽可能多的炮弹,炮弹不能突波冰山,不能让炮弹互相攻击到,问最大能不知多少个? 分析:二分图的经典题目,关键在于怎么建图,图进行两次编号,按行编号,每一行中能攻击到的一块编号成相同的数,每一列同样,然后对行和列有编号的地方进行连边,求一次最大匹配即可,我用最大流求的最大匹配. AC代码: #include <cstdio> #include &

hdu 5093 Battle ships二分图

二分图最大匹配问题 遇到冰山就把行列拆成两个部分.每个部分x也好,y也好只能匹配一次 图画得比较草,将就着看 横着扫一遍,竖着扫一遍,得到编号 一个位置就对应一个(xi,yi)就是X集到Y集的一条边, 由题意,每个点只能被选择一次.所以最大匹配的边数就是答案了. 算法过程 通常都是先贪心求一个匹配,然后开始增广. 寻找增广路的过程: 一个没有和任意边匹配的点叫做未盖点,从左集X中一个未盖点u出发寻找增广路. 从u出发,选一个非匹配边到达Y集中的v,如果v没匹配,那么就找到一条增广路(只要把之前走

hdu 5093 Battle ships 二分匹配

题意:在n×m的方格中,'#'代表iceberg,'*'代表ocean,'o'代表floating ice.战舰只能放在ocean上,在同一行或者同一列不能放两 个战舰除非它们中间有iceberg,求最多能放多少战舰. 思路:二分匹配.每行中连续为'*'的作为X集合中一个点,同样,将每列中连续为'*'的点作为Y集合中的一个点.对原图中每个'*',将其对应的X集合和Y集合中的标号建边,便形成了二分图,对该图求最大匹配.详见代码: /*********************************

HDU 5093 Battle ships(二分图匹配)

该题是一道经典的二分图匹配题目 .  同一列(行)上不能放两个船除非有冰山隔着.对于这种二维平面图,我们很容易想到将行和列分成两个集合,进行二分图匹配,当一个行坐标匹配到一个列坐标时,该格子可以放置船.那么为了使任意两个船都不在同一行或者同一列,除非有冰山,我们可以将每一行中一块连续的只能放置一个船的区域都设成一个编号,同样的按照列也这样处理,这样就相当于将行和列缩点了,接下来用最大流模板套一套就可以了 . 处理二分图还有一种更好的算法,叫匈牙利算法,紫书上没有,先用最大流算法解决吧 . 紫书十

hdu 5093 Battle ships 最大二分匹配

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

Battle ships(二分图,建图,好题)

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

hdu 5093 Battle ships

二分图匹配 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #define maxn 60 6 #define maxd 1500 7 using namespace std; 8 int v[maxd][maxd],vist[maxd],math[maxd]; 9 10 int col[maxn][maxn],row[maxn][maxn]; 1

hdu 5093 Battle ships (二部图+最大匹配)

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