您的位置:首页 > 其它

HDU 1045 Fire Net(图匹配)

2015-08-10 17:16 267 查看
题目大意:
这个是以前做过的一道DFS题目,当时是完全暴力写的。
给你一个N代表是N*N的矩阵,矩阵内 ‘X’代表墙, ‘.’代表通道。
问这个矩阵内最多可以放几个碉堡, 碉堡不能在同一行或者同一列,除非他们中间有墙。

二分图做法思想:我们用行去匹配列,判断最大匹配数。
我们需要重新构图, 假如一行中 ( ..X..X.. ) 那么在这一行中我们其实是可以分割到三个不同的行(因为中间隔有X)。然后对这个三个行进行编号。同理列也是一样的。当我们完全构好图后就可以做完全匹配了,其他的跟HDU 1083 Courses(最大匹配模版题) 差不多。
吐槽一下杭电,代码写好了提交用C++WA G++过 妈蛋

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 50
bool G[maxn][maxn];///重新构图存储
bool vis[maxn];///标记点是否被遍历过
char maps[maxn][maxn];///地图存储
int P[maxn];///第 i  行匹配的第 P[i]列
int n, m, N;///重构图后是m行 n列
struct Node
{
int x, y;
}NodeInfo[maxn][maxn];///保存每个点重构图后所在的行和列

bool Find(int u)
{
for(int i=0; i<n; i++)
{
if(G[u][i] && !vis[i])
{
vis[i] = true;
if( P[i] == -1 || Find(P[i]))
{
P[i] = u;
return true;
}
}
}
return false;
}
void MakeMaps()
{
m = 0, n = 0;///行标记 和 列标记

for(int i=0; i<N; i++)///第 i 行
{
for(int j=0; j<N; j++)
{
if(maps[i][j] == '.')
NodeInfo[i][j].x = m;
if(maps[i][j+1] == 'X' || maps[i][j+1] == 0)
m ++;
}
}

for(int i=0; i<N; i++)///第 i 列
{
for(int j=0; j<N; j++)
{
if(maps[j][i] == '.')
NodeInfo[j][i].y = n;
if(maps[j+1][i] == 'X' || maps[j+1][i] == 0)
n ++;
}
}

for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
int x = NodeInfo[i][j].x;
int y = NodeInfo[i][j].y;

if(maps[i][j] == '.')
G[x][y] = true;
}
}
}

int main()
{
while(scanf("%d", &N), N)
{

memset(G, 0, sizeof(G));
memset(P, -1, sizeof(P));
memset(maps, 0, sizeof(maps));

for(int i=0; i<N; i++)
scanf("%s", maps[i]);

MakeMaps();
int ans = 0;
for(int i=0; i<m; i++)
{
memset(vis, false, sizeof(vis));
if( Find(i) )
ans ++;
}
printf("%d\n", ans);
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: