Fire Net HDU - 1045(二分匹配)

把每一列中相邻的 .  缩为一个点 作为二分图的左边

把每一行中相邻的  .  缩为一个点 作为二分图的右边

然后求最大匹配即可

这题用匈牙利足够了。。。然而。。我用了hk。。。有点大材小用的感觉///

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 10010, INF = 0x7fffffff;
int dx[maxn], dy[maxn], cx[maxn], cy[maxn], used[maxn];
int row[5][5], col[5][5];
int nx, ny, dis;
vector<int> G[40005];
char str[5][5];
int n;
int bfs()
{
    queue<int> Q;
    dis = INF;
    mem(dx, -1);
    mem(dy, -1);
    for(int i=1; i<=nx; i++)
    {
        if(cx[i] == -1)
        {
            Q.push(i);
            dx[i] = 0;
        }
    }
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        if(dx[u] > dis) break;
        for(int v=0; v<G[u].size(); v++)
        {
            int i = G[u][v];
            if(dy[i] == -1)
            {
                dy[i] = dx[u] + 1;
                if(cy[i] == -1) dis = dy[i];
                else
                {
                    dx[cy[i]] = dy[i] + 1;
                    Q.push(cy[i]);
                }
            }
        }
    }
    return dis != INF;
}

int dfs(int u)
{
    for(int v=0; v<G[u].size(); v++)
    {
        int i = G[u][v];
        if(!used[i] && dy[i] == dx[u] + 1)
        {
            used[i] = 1;
            if(cy[i] != -1 && dis == dy[i]) continue;
            if(cy[i] == -1 || dfs(cy[i]))
            {
                cy[i] = u;
                cx[u] = i;
                return 1;
            }
        }
    }
    return 0;
}

int hk()
{
    int res = 0;
    mem(cx, -1);
    mem(cy, -1);
    while(bfs())
    {
        mem(used, 0);
        for(int i=1; i<=nx; i++)
        {
            if(cx[i] == -1 && dfs(i)) res++;
        }
    }
    return res;
}

int main()
{
    while(cin>> n && n)
    {

        for(int i=0; i<100; i++) G[i].clear();
        mem(row, -1);
        mem(col, -1);
        nx = ny = 1;
        for(int i=0; i<n; i++)
        {
            cin>> str[i];
        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                if(str[i][j] == ‘.‘ && row[i][j] == -1)
                {
                    for(int k=j; str[i][k]==‘.‘ && k<n; k++)
                        row[i][k] = nx;
                    nx++;
                }
                if(str[j][i] == ‘.‘ && col[j][i] == -1)
                {
                    for(int k=j; str[k][i]==‘.‘ && k<n; k++)
                        col[k][i] = ny;
                    ny++;
                }
            }
        }
        nx -= 1, ny -= 1;
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                if(str[i][j] == ‘.‘)
                    G[row[i][j]].push_back(nx + col[i][j]), G[nx + col[i][j]].push_back(row[i][j]);

        cout<< hk() <<endl;

    }

    return 0;
}

搜索写法:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 6, INF = 0xfffffff;
typedef long long LL;
char str[maxn][maxn];
int vis[maxn][maxn];
int n, minn;
int check(int x,int y)
{
    for(int i=x-1; i>=0; --i)
    {
        if(vis[i][y])
            return 0;
        if(str[i][y] == ‘X‘)
            break;
    }
    for(int i=y-1; i>=0; --i)
    {
        if(vis[x][i])
            return 0;
        if(str[x][i] == ‘X‘)
            break;
    }
    return 1;
}

void dfs(int inx, int k)
{
    if(inx == n*n)
    {
        minn = max(k, minn);
        return;
    }

    int x = inx / n;
    int y = inx % n;
    if(str[x][y] == ‘.‘ && check(x,y))
    {
        vis[x][y] = 1;
        dfs(inx+1, k+1);
        vis[x][y] = 0;
    }
    dfs(inx+1, k);
}

int main()
{
    while(cin>>n && n)
    {
        minn = -INF;
        mem(vis,0);
        mem(str,0);
        for(int i=0;i<n;i++)
            cin>>str[i];
        dfs(0,0);
        cout<<minn<<endl;

    }

    return 0;
}

原文地址:https://www.cnblogs.com/WTSRUVF/p/9309488.html

时间: 2024-10-18 13:59:16

Fire Net HDU - 1045(二分匹配)的相关文章

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

Fire Net HDU 1045

简单深搜,可以完全暴力,不会超时的. #include<iostream> #include<cstring> #include<cmath> using namespace std; #define MAX(a,b) (a>b?a:b) char maze[10][10]; int n, maxn; void DFS(int step,int count); int cheak(int x, int y); int main() { int i; while(s

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 5093 二分匹配

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

Battle ships HDU - 5093二分匹配

Battle shipsHDU - 5093 题目大意:n*m的地图,*代表海洋,#代表冰山,o代表浮冰,海洋上可以放置船舰,但是每一行每一列只能有一个船舰(类似象棋的車),除非同行或者同列的船舰中间有冰山挡着,问最多能放多少个船舰? 之前做过一个放置炮的,那时数据小直接暴力加搜索就A了,然而这题暴力搜索的话,直接了当的TLE,没办法只好去学新东西了.二分图这个概念只有在之前的题目中做过匈牙利的板子题,可是具体概念和思路并不了解,这题也正好提醒了我去深入了解.但最近需要做的事情较大,一直想整理的

(匹配)Fire Net --hdu --1045

链接: http://acm.hdu.edu.cn/showproblem.php?pid=1045 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82834#problem/A 一看原题,先用搜索写一下,还是要学学匹配吧! 以前的代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> us

A - Fire Net - hdu 1045(二分图匹配)

题意:一个阵地可以向四周扫射,求出来最多能修多少个阵地,墙不可以被扫射透,阵地不能同行或者或者列(有墙隔着例外) 分析:很久以前就做过这道题..当时是练习深搜来着,不过时间复杂度比较高,现在再看突然发现原来可以用二分图匹配来做,时间soso的 ****************************************************************** #include<stdio.h>#include<string.h>#include<algorit

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