给你一个地图,每个天线最多可以覆盖相邻的两个房子,问你最少用多少个天线可以覆盖全部房子。

思路:先对所有的房子编号,然后对一个房子x如果它正下方或者右方有房子y, 那么e[x][y]=e[y][x]=1;

那么最大匹配ans/2就是能够覆盖两个房子的天线数,那么剩下的房子,就每一个都必须用一个天线来匹配。

能够覆盖两个房子的天线数: ans/2
单独覆盖一个房子的天线数: 所有的点N-ans
所有的房子数:N-ans+ans/2 = N-ans/2

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>

using namespace std;

int n,m;//顶点数n和边的数目m
int e[510][510];//保存一个无向图
int book[510];//每次都标记那个去了和那个没去
int match[510];//标记匹配
#define inf 9999//假设的无穷大
int dfs (int u)
{
    int i;
    for (i=1;i<=n;i++)
    {
        if (book[i]==0&&e[u][i]==1)//这个点在同一次上没去过,而且他们能联通
        {
            book[i]=1;//这个点已经尝试过了
            if (match[i]==0||dfs(match[i]))//这个点还没有被匹配,
                //或者,他可以匹配其他的人
            {
               //他们就能够匹配
                match[i]=u;//判断哪个,就是修改那个
                //match[u]=i;不用的,错误的
                return 1;
            }
        }
    }
    return 0;
}

int work()
{
    memset(match, 0, sizeof(match));
    int i_count=0;
    for (int i=1;i<=n;i++)//尝试遍历每一个顶点
    {
        memset (book,0,sizeof(book));
        if (dfs(i))
        {
            i_count++;//若能找到新的匹配,就++
        }
    }

    return i_count;
}

char mp[50][50];
int id[50][50];
int main ()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf ("%d%d",&n,&m);//输入顶点数n和边的数目m
        memset(e, 0, sizeof(e));
        memset(id, 0, sizeof(id));
        for(int i=0;i<n;i++)
        {
            scanf("%s",mp[i]);
        }
        int N=n;
        n=0;
        for(int i=0;i<N;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(mp[i][j]=='*')
                {
                    id[i][j]=++n;
                }
            }
        }
        for(int i=0;i<N;i++)
        {
            for(int j=0;j<strlen(mp[i]);j++)
            {
                if(mp[i][j]=='*')
                {
                    if(i+1<N&&mp[i+1][j]=='*')
                    {
                        //cout<<id[i][j]<<" "<<id[i+1][j]<<endl;
                        e[id[i][j]][id[i+1][j]]=1;
                        e[id[i+1][j]][id[i][j]]=1;
                    }
                    if(j+1<m&&mp[i][j+1]=='*')
                    {
                        e[id[i][j]][id[i][j+1]]=1;
                        e[id[i][j+1]][id[i][j]]=1;
                    }
                }
            }
        }

        int ans=work();
        printf ("%d\n",n-ans/2);
    }

    return 0;
}