• Uncle Tom's Inherited Land*


    最大匹配问题  

    题意:题目意思:
    给定一个  n * m 的矩阵格子, 第二行给定一个k值表示池塘,接下来给出池塘坐标,要求的就是在不是池塘的区域用1 * 2 的小矩形填充它 ,问 最多能填充几个小矩形,并且打印出所有矩阵!

    这题拿到手毫无头绪 是这个专题最难的一题了

    这题值得多打几遍

    #include<bits/stdc++.h>
    using namespace std;
    #define N 105
    
    int mp[N][N];
    int used[N];
    int vis[N];
    int n,m,r,c;
    int dx[4]={0,1,0,-1};
    int dy[4]={1,0,-1,0};
    int flag[N][N];
    int ans[N][2];
    int cnt;
    vector<int>g[N*N];
    bool dfs(int  x)
    {
        for(int j=0;j<g[x].size();j++)
        {
            if(!used[ g[x][j] ]) //所有的j都改为了g[x][j]
            {
                used[ g[x][j] ]=1;
                if(!vis[ g[x][j] ]||dfs(vis[ g[x][j] ]))
                  {
                      vis[ g[x][j] ]=x;
                      return true;
                  }
            }
        }
        return false;
    }
    
    int find1(void)
    {    int ans=0;
          memset(vis,0,sizeof(vis));
         for(int i=1;i<=cnt-1;i++)
           {
               memset(used,0,sizeof(used));
               if(dfs(i))ans++;
           }
           return ans;
    }
    
    bool inmap(int x,int y)
    {
        if(x>=1&&x<=n&&y>=1&&y<=m)return true;
        else return false;
    }
    
    int main()
    {
       while(scanf("%d%d",&n,&m),n||m)
       {
           memset(mp,0,sizeof(mp));
           memset(flag,0,sizeof(flag));
           memset(ans,0,sizeof(ans));
           for(int i=0;i<=N*N;i++)g[i].clear();
           int q;
           scanf("%d",&q);
           while(q--)
           {
               int a,b;
               scanf("%d%d",&a,&b);
               mp[a][b]=1;
           }
            cnt=1;
           for(int i=1;i<=n;i++)//扫描各个点  进行离散化
            for(int j=1;j<=m;j++)
               if(mp[i][j]==0)
                {
                  ans[cnt][0]=i;
                  ans[cnt][1]=j;//这个数组用的巧妙!!
                  flag[i][j]=cnt++;//从小到大标记各个有效点
                }
            for(int i=1;i<=n;i++)
             for(int j=1;j<=m;j++)
                if(flag[i][j])
                 if( 1&(i+j) )//只处理奇数的  可以提高效率 否则的话 ans为两倍(匹配两次) 并且打印各个点就会出错!!很重要
                {
                 for(int k=0;k<4;k++)//类似dfs   扫描一个点 将其匹配的点(就是相邻点)存入匹配向量!!!
                 {
                    int x=i+dx[k];
                    int y=j+dy[k];
                     if(inmap(x,y)&&flag[x][y])
                        g[ flag[i][j] ].push_back( flag[x][y] );
                 }
                }
           printf("%d
    ",find1());
           for(int i=1;i<cnt;i++)//使用vis数组来打印 !这时用上了之前所处理的记录数组
             if(vis[i])
           {
               printf("(%d,%d)--(%d,%d)
    ", ans[i][0],ans[i][1],ans[ vis[i] ][0],ans[ vis[i] ][1]  );
           }
          printf("
    ");
       }
    }
  • 相关阅读:
    php 3des加密 兼容JAVA 多么痛的领悟呀
    主机序和网络序
    不用递归实现无限分类数据的树形格式化
    python学习笔记之open函数的用法
    据说是百度面试题(1)
    YII+DWZ三级城市联动挂件
    wpf 报错: 在 AddNew 或 EditItem 事务过程中不允许“DeferRefresh”。
    MVVM了解
    纪念2015年上半年
    c# 委托与事件
  • 原文地址:https://www.cnblogs.com/bxd123/p/10372433.html
Copyright © 2020-2023  润新知