HDU 1045 (0ms运行时间,傻B似的建图方法)

知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1045

题目分析:
看到网上博客,大都是缩点建图或者是枚举状压之类。
而我的想法是根据行列进行建图,ch6802是这个题的简单版。 我看了ch6802的题解之后, 发现这个题用ch6802的方法一样可以建图,知识麻烦一点。 便想试一下,我首先按列给图中空地打了标记。 这些标记便是建图时候的y点。然后,遍历整个图,进行建图。 遍历时,时刻更新行结点。

#include"stdio.h"
#include"string.h"
#include"algorithm"
using namespace std;

int n;
char str[5][6];
int head[100],Next[100],ver[100];
int match[100],visit[100],tot,top;
void add(int x,int y)
{
    ver[++ top] = y; Next[top] = head[x]; head[x] = top;
    //ver[++ top] = x; Next[top] = head[y]; head[y] = top;
}
void init()
{
    tot = 2 * n; top = 0;
    for(int i = 0; i < 100; i ++){
        head[i] = Next[i] = ver[i] = 0;
        match[i] = visit[i] = 0;
    }
}
bool dfs(int x)
{
    for(int i = head[x],y; i; i = Next[i])
    if(!visit[y = ver[i]] && y != x){
        visit[y] = 1;
        if(!match[y] || dfs(match[y])){
            match[y] = x; return true;
        }
    }
    return false;
}
int main()
{
    while(~scanf("%d",&n) && n)
    {
        init();
        for(int i = 1; i <= n;i ++)
            scanf("%s",str[i] + 1);
        int digit[6][6],limit = 1;memset(digit,0,sizeof(digit));
        for(int i = 1; i <= n; i ++)
            {
                int j = 1; while(str[j][i] == 'X' && j <= n) j ++;
                int mark = 0;
                for(; j <= n;)
                {
                    if(str[j][i] == '.')
                        digit[j][i] = limit,j ++,mark = 1;
                    else
                    {
                        while(str[j][i] == 'X' && j <= n) j ++;
                        if(j <= n)
                        limit ++;
                    }
                }
                if(mark == 1) limit ++;
            }
        /*for(int i = 1; i<= n; i ++)
        {for(int j = 1;j <= n; j ++)
               printf("%d ",digit[i][j]);
               printf("\n");
        }*/
        tot = n + limit;
        for(int i = 1; i <= n;i ++)
            {
                int x = i;int cnt = 0; int X = tot;
                int j = 1;
                while(str[i][j] == 'X') j ++;
                for(; j <= n; j ++)
                {
                    int mark = 0;
                    while(str[i][j] == 'X' && j <= n)
                        {
                            j ++;
                            if(mark == 0)
                                cnt ++;
                            mark = 1;
                            if(j == n + 1) cnt --;
                        }
                    if(j > n) break;
                    if(str[i][j] == '.' && cnt == 0)
                        add(x,n + digit[i][j]);
                    if(cnt != 0)
                    {
                        int y = X + cnt;
                        add(y,n + digit[i][j]);
                    }
                }
                tot += cnt;
            }
        int ans = 0;
        for(int i = 1; i <= tot; i ++){
            memset(visit,0,sizeof(visit));
            if(dfs(i)) ans ++;
        }
        printf("%d\n",ans);
       /*for(int i = 1; i <= tot; i ++)
        {
            printf("%d : ",i);
            for(int j = head[i]; j; j = Next[j])
                printf("%d ",ver[j]);
            printf("\n");
        }*/
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值