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
在南极洲的海面上,有海面,有冰山,有浮冰,你需要在海面上放置战舰,要保证每一行每一列只有一艘战舰,但是如果有冰山的话,冰山可以分出新的一行或一列,问你最多能放置多少架战舰?
这题居然是道二分图的题目!要不是在专项训练里我是不会想到二分图的。大致思路就是将这个图用行和列分别放置战舰,将这些被放置的战舰标上号,这些号码就是新创的图的各个节点,然后再遍历原图能放置战舰的点,将转化后新结点建边,跑一边Hungary就可以求出这个新图的最大匹配,也就是答案。
(PS:这道题还有网络流的做法)
这是个盗来的图,O表示可以放的点,X表示冰山,空着的就是浮冰
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
const int MAXN =60;
const int MAXM =3600;
int linker[MAXM];
bool used[MAXM];
char mp[MAXN][MAXN];
int row[MAXN][MAXN];
int col[MAXN][MAXN];
bool g[MAXM][MAXM];
int T,m,n;
int r,c;
bool dfs(int u)
{
for(int v=0; v<c; v++)
{
if(g[u][v] && !used[v])
{
used[v]=1;
if (linker[v]==-1 || dfs(linker[v]))
{
linker[v]=u;
return 1;
}
}
}
return 0;
}
int hungary()
{
int res=0;
memset(linker,-1,sizeof(linker));
for(int u=0; u<r; u++)
{
memset(used,0,sizeof(used));
if (dfs(u)) res++;
}
return res;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
scanf("%s",mp[i]);
memset(col,0,sizeof(col));
memset(row,0,sizeof(row));
r=0,c=0;//r,c为新结点的标号
for(int i=0; i<n; i++)//按行转化将可以放置的位置放置战舰
{
for(int j=0; j<m; j++)
{
if(mp[i][j]=='*')//可以放战舰
{
row[i][j]=r;
}
if(mp[i][j]=='#') r++;
}
r++;
}
for(int j=0; j<m; j++)//按列转化
{
for(int i=0; i<n; i++)
{
if (mp[i][j]=='*')
{
col[i][j]=c;
}
if (mp[i][j]=='#') c++;
}
c++;
}
memset(g,0,sizeof(g));
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if (mp[i][j]=='*')
{
g[row[i][j]][col[i][j]]=1;//寻找按行转化与列转化后相同的建边
}
}
}
int ans=hungary();
printf("%d\n",ans);
}
return 0;
}