UVAlive 6156 Sentry Robots

来源:互联网 发布:手机版网络维护软件 编辑:程序博客网 时间:2024/04/30 04:19

题目

题意:

n*m的矩形格子中有一些宝藏,有些点不能经过,每次可以取走一横行,或者一纵行的宝藏,求至少需要多少次取走所有宝藏

题解:

如果没有不能走的点,就是一道经典的二分图匹配的最小点覆盖。考虑障碍,在同一行(或列)被障碍隔开的点就不能算同一行(或列),所以重置坐标即可,进行二分图匹配。

代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;#define maxn 105#define maxm 5005int n,m,k,N,M;int g[maxn][maxn],xx[maxn][maxn],yy[maxn][maxn],result[maxm];bool e[maxm][maxm],state[maxm];int find(int x){    for (int i=1;i<=M;i++)        if (!state[i]&&e[x][i])        {            state[i]=1;            if (!result[i]||find(result[i]))            {                result[i]=x;                return 1;            }        }    return 0;}int hungry(){    int res=0;    memset(result,0,sizeof(result));    for (int i=1;i<=N;i++)    {        memset(state,0,sizeof(state));        if (find(i)) res++;    }    return res;}int main(){    //freopen("/home/moor/Code/input","r",stdin);    int cas,x,y;    scanf("%d",&cas);    while (cas--)    {        scanf("%d%d",&n,&m);        scanf("%d",&k);        memset(g,0,sizeof(g));        for (int i=1;i<=k;i++)        {            scanf("%d%d",&x,&y);            g[x][y]=1;        }        scanf("%d",&k);        for (int i=1;i<=k;i++)        {            scanf("%d%d",&x,&y);            g[x][y]=2;        }        N=0;        for (int i=1;i<=n;i++)        {            int j=1;            while (j<=m)            {                N++;                while (j<=m&&g[i][j]!=2) xx[i][j++]=N;                while (j<=m&&g[i][j]==2) j++;            }        }        M=0;        for (int i=1;i<=m;i++)        {            int j=1;            while (j<=n)            {                M++;                while (j<=n&&g[j][i]!=2) yy[j++][i]=M;                while (j<=n&&g[j][i]==2) j++;            }        }        memset(e,0,sizeof(e));        for (int i=1;i<=n;i++)            for (int j=1;j<=m;j++)                if (g[i][j]==1) e[xx[i][j]][yy[i][j]]=1;        printf("%d\n",hungry());    }    return 0;}


原创粉丝点击