TOJ 1629 Muddy Fields -- 二分图匹配(最小点覆盖)

针对一块混合草地与泥泞地的区域,通过使用宽度固定、长度不限的木板覆盖所有泥泞地,同时不覆盖草地,求解所需最少木板数量的问题。采用匈牙利算法进行解答。

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

题目链接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1629

题目大意:有一块大小为n * m的地,其中一些位置是草地,一些位置是泥泞地,要用一些长无限制、宽为1的木板覆盖所有的泥泞地,但不能覆盖草地,木板可以重叠,问最少要多少块木板。

分析:最小点覆盖问题,匈牙利方法。

#include 
  
   
#include 
   
    
#include 
    
     
#include 
     
      
#include 
      
       
#include 
        #include 
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #define mp make_pair #define X first #define Y second #define MEMSET(a, b) memset(a, b, sizeof(a)) using namespace std; typedef unsigned int ui; typedef long long ll; typedef unsigned long long ull; typedef pair
                  
                    pii; typedef vector
                   
                     vi; typedef vi::iterator vi_it; typedef map
                    
                      mii; typedef priority_queue
                     
                       pqi; typedef priority_queue
                      
                       , greater
                       
                         > rpqi; typedef priority_queue
                        
                          pqp; typedef priority_queue
                         
                          , greater
                          
                            > rpqp; const int MAX_SIZE = 50 + 2; char str[MAX_SIZE][MAX_SIZE]; vi link[MAX_SIZE * MAX_SIZE / 2]; int hcnt[MAX_SIZE][MAX_SIZE]; int rsum, csum; bool vis[MAX_SIZE * MAX_SIZE / 2]; int pre[MAX_SIZE * MAX_SIZE / 2]; void input(int &r, int &c) { if (scanf("%d%d\n", &r, &c) != 2) { exit(EXIT_FAILURE); } for (int i = 0; i < r; ++i) { gets(str[i]); } } void build_graph(int r, int c) { int i, j; for (i = 0; i < r; ++i) { bool flag = false; for (j = 0; j < c; ++j) { if (str[i][j] == '.') { flag = false; } else { if (!flag) { flag = true; ++rsum; } hcnt[i][j] = rsum; } } } for (j = 0; j < c; ++j) { bool flag = false; for (i = 0; i < r; ++i) { if (str[i][j] == '.') { flag = false; } else { if (!flag) { flag = true; ++csum; } link[hcnt[i][j]].push_back(csum); } } } } int dfs(int u) { for (vi_it it = link[u].begin(); it != link[u].end(); ++it) { int v = *it; if (!vis[v]) { vis[v] = true; if (!pre[v] || dfs(pre[v])) { pre[v] = u; return 1; } } } return 0; } void solve() { int ret = 0; for (int i = 1; i <= rsum; ++i) { MEMSET(vis, 0); ret += dfs(i); } printf("%d\n", ret); } int main(int argc, char *argv[]) { // freopen("D:\\in.txt", "r", stdin); int r, c; input(r, c); build_graph(r, c); solve(); return 0; } 
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
      
     
    
   
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值