tjut 3529

# include<cstdio>  
# include<iostream>  
# include<cstring>  
# include<algorithm>  
# define MAXM 20  
# define MAXN 60000  
# define MAXL 300  
# define INF 0x7FFFFFFF  
  
using namespace std;  
  
char s[MAXM][MAXM];  
int L[MAXN], R[MAXN], U[MAXN], D[MAXN];  
int H[MAXL], S[MAXL], C[MAXN];  
int pos[MAXM][MAXM], ans, size;  
bool vis[MAXL];  
  
void Init(int n)  
{  
    int i;  
    for (i = 0; i <= n; i++)  
    {  
        R[i] = i + 1;  
        L[i + 1] = i;  
        U[i] = D[i] = i;  
        S[i] = 0;  
    }  
    R[n] = 0;  
    size = n + 1;  
}  
void Link(int r, int c)  
{  
    U[size] = c;  
    D[size] = D[c];  
    U[D[c]] = size;  
    D[c] = size;  
    if (H[r] < 0)  
        H[r] = L[size] = R[size] = size;  
    else  
    {  
        L[size] = H[r];  
        R[size] = R[H[r]];  
        L[R[H[r]]] = size;  
        R[H[r]] = size;  
    }  
    S[c]++;  
    C[size++] = c;  
}  
void Remove(int c)  
{  
    int i;  
    for (i = D[c]; i != c; i = D[i])  
    {  
        L[R[i]] = L[i];  
        R[L[i]] = R[i];  
    }  
}  
void Resume(int c)  
{  
    int i;  
    for (i = D[c]; i != c; i = D[i])  
        L[R[i]] = R[L[i]] = i;  
}  
int A()  
{  
    int i, j, k, res;  
    memset(vis, false, sizeof(vis));  
    for (res = 0, i = R[0]; i; i = R[i])  
    {  
        if (!vis[i])  
        {  
            res++;  
            for (j = D[i]; j != i; j = D[j])  
            {  
                for (k = R[j]; k != j; k = R[k])  
                    vis[C[k]] = true;  
            }  
        }  
    }  
    return res;  
}  
void Dance(int now)  
{  
    if (R[0] == 0)  
        ans = min(ans, now);  
    else if (now + A() < ans)  
    {  
        int i, j, temp, c;  
        for (temp = INF,i = R[0]; i; i = R[i])  
        {  
            if (temp > S[i])  
            {  
                temp = S[i];  
                c = i;  
            }  
        }  
        for (i = D[c]; i != c; i = D[i])  
        {  
            Remove(i);  
            for (j = R[i]; j != i; j = R[j])  
                Remove(j);  
            Dance(now + 1);  
            for (j = L[i]; j != i; j = L[j])  
                Resume(j);  
            Resume(i);  
        }  
    }  
}  
int main(void)  
{  
    int n, m, i, j, k, r;  
    while (~scanf("%d%d", &n, &m))  
    {  
        memset(pos, 0, sizeof(pos));  
        for (i = k = 0; i < n; i++)  
        {  
            for (j = 0; j < m; j++)  
            {  
                scanf(" %c", &s[i][j]);  
                if (s[i][j] == '#')  
                {  
                    k++;  
                    pos[i][j] = k;  
                }  
            }  
        }  
        Init(k);  
        for (i = r = 0; i < n; i++)  
        {  
            for (j = 0; j < m; j++)  
            {  
                H[++r] = -1;  
                if (s[i][j] == '.')  
                {  
                    for (k = j + 1; k < m && s[i][k] == '.'; k++)  
                        ;  
                    if (s[i][k] == '#')  
                        Link(r, pos[i][k]);  
                    for (k = j - 1; k >= 0 && s[i][k] == '.'; k--)  
                        ;  
                    if (s[i][k] == '#')  
                        Link(r, pos[i][k]);  
                    for (k = i + 1; k < n && s[k][j] == '.'; k++)  
                        ;  
                    if (s[k][j] == '#')  
                        Link(r, pos[k][j]);  
                    for (k = i - 1; k >= 0 && s[k][j] == '.'; k--)  
                        ;  
                    if (s[k][j] == '#')  
                        Link(r, pos[k][j]);  
                }  
            }  
        }  
        ans = INF;  
        Dance(0);  
        printf("%d\n", ans);  
    }  
    return 0;  
}  

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值