【HDOJ 1045】Fire Net--二分图

来源:互联网 发布:淘宝王者荣耀充值便宜 编辑:程序博客网 时间:2024/06/05 08:57

【HDOJ 1045】Fire Net

数据量很小 dfs暴力可过 不过最近在学二分图 想了想二分图的做法
根据题目要求 不能让同行或者同列出现一个以上的车(无墙状态下 因此根据行 列 构建二分图 每行上联通的一段区间标为同一个号 列同理标注 然后再遍历 发现有交界时将行与列联通 最后进行一次二分最大匹配即可

代码如下:

#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>using namespace std;bool mp[17][17],vis[17];int idx[5][5],idy[5][5];char qp[5][6];int n,link[17],p1,p2;void Sd(){    int i,j,k;    for(p1 = 0,i = 1; i <= n; ++i)    {        for(j = 1; j <= n; ++j)        {            if(j == 1 || qp[i][j-1] == 'X') p1++;            idx[i][j] = p1;        }    }    for(p2 = 0,j = 1; j <= n; ++j)    {        for(i = 1; i <= n; ++i)        {            if(i == 1 || qp[i-1][j] == 'X') p2++;            idy[i][j] = p2;        }    }    for(i = 1; i <= n; ++i)    {        for(j = 1; j <= n; ++j)        {            if(qp[i][j] == '.') mp[idx[i][j]][idy[i][j]] = 1;        }    }}bool can(int p){    int i;    for(i = 0; i <= p2; ++i)    {        if(!vis[i] && mp[p][i])        {            vis[i] = true;            if(link[i] == -1 || can(link[i]))            {                link[i] = p;                return 1;            }        }    }    return 0;}int main(){    int i,j,cnt,sum;    while(~scanf("%d",&n) && n)    {        cnt = 0;        for(i = 1; i <= n; ++i)            scanf("%s",qp[i]+1);        memset(mp,0,sizeof(mp));        Sd();        memset(link,-1,sizeof(link));        for(i = 0; i <= p1; ++i)        {            memset(vis,0,sizeof(vis));            if(can(i)) cnt++;        }        printf("%d\n",cnt);    }    return 0;}
0 0