poj 2226 Muddy Fields

本文详细探讨了如何通过算法优化解决二维矩阵中覆盖所有洼地所需的最少木板数量问题。首先,文章介绍了将横向和纵向连续的洼地进行编号的方法,并利用二分匹配算法来寻找最小覆盖点。接着,通过代码实现和实例分析,展示了如何通过调整二分匹配过程中的变量顺序来避免错误答案(WA)。最后,文章提供了完整的代码示例和运行结果,帮助读者理解和实践该算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 题意 :有R×C方阵,'*'铺表示洼地,需要上宽度为1的木板,长度不限,只能横放或竖放.木板可以重叠,但不能覆盖'.'求覆盖所有'*'洼地所用的最少木板数.
 
构图: 将所有横向且连续(一个或以上)的'*'看成一个点并对其进行编号,所有的编号都为集合X内的编号总数为uN。同样地,将所有的竖向且连续(一个或以上)的'*'看成一个点并对其编号,所有的编号都为集合Y内的编号总数为vN.然后用二分匹配,最小覆盖点等于最大匹配。
 
疑问的是:在二分匹配中代码部分vU和uN交换为什么就WA???搞不明白。。。从X集合向Y用dfs和Y向X用dfs理应是一样的哈.

 


 

#include <iostream>
#include<cstring>
using namespace std;

int  map[2255][2555];
int f[5509];
int mat[5500];
int vN,uN;

int dfs(int u)
{
    int i,t;
    for(i=1;i<=vN;i++)
    {
        if(!f[i]&&map[u][i])
        {
            f[i]=1;
            t=mat[i];
            if(!t||dfs(t))
            {
                mat[i]=u;
                return 1;
            }
        }
    }
    return 0;
}

int match()
{
    int i;
    int sum=0;
    memset(mat,0,sizeof(mat));
    for(i=1;i<=uN;i++)
    {
        memset(f,0,sizeof(f));
        if(dfs(i))
        {
             sum++;
        }
    }
    return sum;
}

int main()
{
    int i, j, n, m;
    cin>>n>>m;
    int cx[500][500],cy[500][500];
    char map1[55][55];
    memset(map, 0, sizeof(map));
    for(i = 1; i <= n; i++)
      for(j = 1; j <= m; j++)
         cin>>map1[i][j];

    vN = uN = 0;
    for(i = 1; i <= n; i++)
       for(j = 1; j <= m; j++)
          if(map1[i][j] == '*')
          {
             uN++;
             while(j <= m && map1 [i][j] == '*')
             {
                cx[i][j] = uN;
                j++;
             }
          }

   for(j = 1; j <= m; j++)
      for(i = 1; i <= n; i++)
         if(map1 [i][j] == '*')
         {
            vN++;
            while(i <= n && map1 [i][j] == '*')
            {
               cy[i][j] = vN;
               i++;
            }
          }

   for(i = 1; i <= n; i++)
       for(j = 1; j <= m; j++)
          if(map1 [i][j] == '*')
          {
             map[cx[i][j]][cy[i][j]] = 1;
          }
   cout<<match()<<endl;

   return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值