POJ 3020 Antenna Placement 解题报告

    题意就不说了,求二部图最大匹配。

    问题是怎么建图……

    给定的条件中,h<40,w<10,所以笔者直接默认所有情况的地图都是40*10,当然,超出范围的便是空城o。

    然后给城市编号。一个城市只能和上下左右4个城市公用天线。换个换说就像国际象棋的棋盘一样,黑色格子与白色格子自然分成了二部图。黑色只能和白色匹配。

    编号也很简单了。从第一行开始,第一格是黑色城市1,然后白色城市1,然后黑色城市2,白色城市2……因为所有的图都默认一样大小,所以编号可以重用。

    为了方便知道(i,j)到底是黑色还是白色,我们可以用正数编号表示黑色,负数编号表示白色。

    然后求最大匹配,直接匈牙利过去就好了。

    贴代码,0MS

#include <cstdio>
#include <cstring>

const int maxn=201;
bool mp[maxn][maxn];
bool vis[maxn];
int link[maxn];
int No[41][10];
int n;

bool DFS(int x)
{
    for(int y=1;y<=n;y++)
    {
        if(mp[x][y] && !vis[y])
        {
            vis[y]=true;
            if(link[y]==0 || DFS(link[y]))
            {
                link[y]=x;
                return true;
            }
        }
    }
    return false;
}

int maxMartch()
{
    int count=0;
    for(int x=1;x<=n;x++)
    {
        memset(vis,0,sizeof(vis));
        if(DFS(x))
            count++;
    }
    return count;
}

int main()
{
    int T;
    scanf("%d",&T);

    int index=2;
    for(int i=0;i<40;i++)
        for(int j=0;j<10;j++,index++)
            No[i][j]=(index/2)*((index+i)%2?-1:1);
    n=200;

    while(T--)
    {
        int num=0;
        int w,h;
        scanf("%d%d",&h,&w);
        if(w%2)
            w++;

        char str[2][20];
        memset(mp,0,sizeof(mp));
        memset(link,0,sizeof(link));
        memset(str,0,sizeof(str));
        for(int i=0;i<h;i++)
        {
            scanf("%s",str[i&1]);
            if(str[i&1][0]=='*')
            {
                num++;
                if(str[1-i&1][0]=='*')
                {
                    if(No[i][0]>0)
                        mp[No[i][0]][-No[i-1][0]]=true;
                    else
                        mp[No[i-1][0]][-No[i][0]]=true;
                }
            }
            for(int j=1; j<w; j++)
            {
                if(str[i&1][j]=='*')
                {
                    num++;
                    if(str[i&1][j-1]=='*')
                    {
                        if(No[i][j]>0)
                            mp[No[i][j]][-No[i][j-1]]=true;
                        else
                            mp[No[i][j-1]][-No[i][j]]=true;
                    }

                    if(str[1-i&1][j]=='*')
                    {
                        if(No[i][j]>0)
                            mp[No[i][j]][-No[i-1][j]]=true;
                        else
                            mp[No[i-1][j]][-No[i][j]]=true;
                    }
                }
            }
        }
        printf("%d\n",num-maxMartch());
    }
}

    整个建图是自己想的,好像略似繁琐……不过还好,比赛的时候估计也能这么想到吧。

posted @ 2013-07-28 20:49  SF-_-  阅读(389)  评论(0编辑  收藏  举报