hdu1045 Fire Net(最大二分匹配)

这个题目因为数据范围比较小,貌似可以用多种算法求解,本人目前暂时使用最大二分图匹配,使用的是行和列匹配。。。。。水平不高,开的数组比较多,mapr表示对地图的行进行编号,每行中被X隔开的地方编号,同理将列也如是编好序号,这样都编号完毕后开始组建二分图,以行和列的编号作为二分图的X,Y集合,然后计算最大二分匹配即可。

 

例如:

4
.X..
....
XX..
....
则行标号结果为:

4
1 -1 2 2

2 2 2 2
-1 -1 33
4 4 4 4

同理得列编号。。。然后二分匹配。

代码如下:

# include <iostream>
using namespace std;
int n;
const int Go[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
char map[4][4];
int mapr[4][4];
int mapl[4][4];
int mape[20][20];
int flag[20], mark[20];
int rr=0, ll=0;
int dfs(int x)
{
    for (int i = 1; i <= ll; i ++){
        if (!(mape[x][i]) || flag[i]){
           continue;
        }   
        flag[i] = 1;
        if (!mark[i]|| dfs(mark[i])){
           mark[i] = x;
           return 1;            
        }
    }
    return 0;
}
int main()
{
   
    while (scanf("%d", &n) != EOF && n){
          memset(mapl, 0, sizeof(mapl));
          memset(mapr, 0, sizeof(mapr));
          memset(mape, 0, sizeof(mape));
          memset(mark, 0, sizeof(mark));
          for (int i = 1; i <= n; i ++){getchar();
              for (int j = 1; j <= n; j ++){
                 
                  scanf("%c", &map[i][j]);
                  if (map[i][j] == 'X'){
                     mapl[i][j] = mapr[i][j] = -1;             
                  }  
              }   
          }
          int p1 = 0;
          int check1 = 0;
          rr =0, ll = 0;
          for (int i = 1; i <= n; i ++){
             
              for (int j = 1; j <= n; j ++){
                  while (mapr[i][j] == -1&&j<=n){
                        j ++;     
                  }
                  p1 ++;
                  while (mapr[i][j] != -1&&j<=n){
                        mapr[i][j] = p1;
                        if (rr < p1)rr = p1;
                        j ++;              
                  }
              }   
          }
          int p2 = 0;
          for (int i = 1; i <= n; i ++){
             
              for (int j = 1; j <= n; j ++){
                  while (mapl[j][i] == -1&&j<=n){
                        j ++;     
                  }
                  p2 ++;
                  while (mapl[j][i] != -1&&j<=n){
                        mapl[j][i] = p2;
                        if (ll < p2)ll = p2;
                        j ++;              
                  }
              }   
          }
          for (int i = 1; i <= n; i ++){
              for (int j = 1; j <= n; j ++){
                  if (mapr[i][j]!=-1&&mapl[i][j] != -1){
                     mape[mapr[i][j]][mapl[i][j]] = 1;
                  }   
              }   
          }
          int counter = 0;
          memset(mark, 0, sizeof(mark));
          for (int i = 1; i <= rr; i ++){
              memset(flag, 0, sizeof(flag));
              if (dfs(i)){
                 counter ++;  
              }   
          }
          printf("%d/n", counter);
    }
    return 0;   
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值