前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HDU 1045 Fire Net(二分图匹配或爆搜)

HDU 1045 Fire Net(二分图匹配或爆搜)

作者头像
Ch_Zaqdt
发布2019-01-11 10:50:45
4290
发布2019-01-11 10:50:45
举报
文章被收录于专栏:Zaqdt_ACM

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1045

       题意是有个n*n地图,地图中有空地'.'和墙'X',然后我们要在空地上安置大炮,为了防止大炮打大炮,一行和一列上只能有一台大炮,问最多能放多少大炮。

       比较好想的思路就是爆搜,我们用dfs去一个一个搜,然后判断这行和这列是否已经出现过了,因为数据范围不大,所以搜索可过。还有一种方法感觉挺不好想的,我们按行和列去将块压缩成点,也就是说没有被墙隔开的点都压缩成一个点,然后我们用这些行和列的压缩点去连边,这样我们可以发现相同的行的压缩点和相同列的压缩点上就只能放置一个大炮了,主要就是这伊迪安不太好理解,建议在纸上将两个压缩的图画出来,然后两个压缩后的图进行连边,最后跑一个最大匹配数就好了。


AC代码(爆搜):

代码语言:javascript
复制
#include <bits/stdc++.h>
#define maxn 15
using namespace std;
string str[maxn];
int n,ans;

bool Check(int x,int y){    // 判断这个点之前的行和列是否放置过
  for(int i=x-1;i>=0;i--){
    if(str[i][y] == 'X'){
      break;
    }
    if(str[i][y] == 'O') return false;
  }
  for(int i=y-1;i>=0;i--){
    if(str[x][i] == 'X'){
      break;
    }
    if(str[x][i] == 'O'){
      return false;
    }
  }
  return true;
}

void dfs(int cnt, int xx){  // cnt用来枚举地图 xx表示放置的数量
  if(cnt == n * n){
    ans = max(ans, xx);
    return ;
  }
  int x = cnt / n;    // 行
  int y = cnt % n;    // 列
  if(str[x][y] == '.' && Check(x, y)){
    str[x][y] = 'O';
    dfs(cnt + 1, xx + 1);
    str[x][y] = '.';
  }
  dfs(cnt + 1, xx);
}

int main()
{
  while(~scanf("%d",&n)){
    if(n == 0) break;
    for(int i=0;i<n;i++){
      cin>>str[i];
    }
    ans = 0;
    dfs(0, 0);
    printf("%d\n",ans);
  }
  return 0;
}

AC代码(二分图):

代码语言:javascript
复制
#include <bits/stdc++.h>
#define maxn 15
using namespace std;
string str[maxn];
int xx[maxn][maxn], yy[maxn][maxn];
bool edge[maxn][maxn], vis[maxn];
int pre[maxn];
int n, row, col;

bool dfs(int x){       // 匈牙利算法
  for(int i=1;i<=col;i++){
    if(edge[x][i] && vis[i] == false){
      vis[i] = true;
      if(pre[i] == -1 || dfs(pre[i])){
        pre[i] = x;
        return true;
      }
    }
  }
  return false;
}

int Fun(){
  int sum = 0;
  memset(pre,-1,sizeof(pre));
  for(int i=1;i<=row;i++){      // 从1开始
    memset(vis,false,sizeof(vis));
    if(dfs(i))
      sum ++;
  }
  return sum;
}

int main()
{
  while(~scanf("%d",&n)){
    if(n == 0) break;
    for(int i=0;i<n;i++) cin>>str[i];
    row = col = 0;
    for(int i=0;i<n;i++){           // 将块压缩成点
      for(int j=0;j<n;j++){
        if(str[i][j] == '.'){
          if(j == 0 || str[i][j-1] == 'X') row ++;
          xx[i][j] = row;
        }
        if(str[j][i] == '.'){
          if(j == 0 || str[j-1][i] == 'X') col ++;
          yy[j][i] = col;
        }
      }
    }
    memset(edge,false,sizeof(edge));
    for(int i=0;i<n;i++){             // 枚举点  进行连边
      for(int j=0;j<n;j++){
        if(str[i][j] == '.'){
          edge[ xx[i][j] ][ yy[i][j] ] = true;
        }
      }
    }
    int ans = Fun();
    printf("%d\n",ans);
  }
  return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年11月04日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档