BZOJ 2150 部落战争(最小路径覆盖)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2150

题意:一个n*m的国家,有些是障碍。对于一支军队,每次只能走C*R的格式(比如马是走1*2的格式),而且只能从上往下走。每个格子只能被一个军队经过。问最少需要多少军队可以遍历完所有格子?

思路:上下能连边的连边。最后就是最小路径覆盖。

 

int a[N][N],n,m;

char s[55][55];

 

 

int ID(int i,int j)

{

    return (i-1)*m+j;

}

 

int visit[N],match[N];

 

int r,c;

 

int ok(int x,int y)

{

    return x>=1&&x<=n&&y>=1&&y<=m&&s[x][y]=='.';

}

 

int DFS(int u)

{

    int i;

    FOR1(i,n*m) if(a[u][i]&&!visit[i])

    {

        visit[i]=1;

        if(match[i]==-1||DFS(match[i]))

        {

            match[i]=u;

            return 1;

        }

    }

    return 0;

}

 

int main()

{

    RD(n,m); RD(r,c);

    int i,j;

    FOR1(i,n) RD(s[i]+1);

    FOR1(i,n) FOR1(j,m) if(s[i][j]=='.')

    {

        if(ok(i-c,j-r)) a[ID(i-c,j-r)][ID(i,j)]=1;

        if(ok(i-c,j+r)) a[ID(i-c,j+r)][ID(i,j)]=1;

        if(ok(i-r,j-c)) a[ID(i-r,j-c)][ID(i,j)]=1;

        if(ok(i-r,j+c)) a[ID(i-r,j+c)][ID(i,j)]=1;

    }

    clr(match,-1);

    int ans=0,sum=0;

    FOR1(i,n) FOR1(j,m) if(s[i][j]=='.')

    {

        clr(visit,0);

        ans+=DFS(ID(i,j));

        sum++;

    }

    PR(sum-ans);

}

 

 

 

你可能感兴趣的:(ZOJ)