标签:
题目链接:
http://poj.org/problem?id=1548
题目大意:
在一个N*M(N <= 24,M <= 24)的图中,有很多垃圾, 清理垃圾的机器人从左上角开始清理。已
知机器人只能向右或是向下清理垃圾,在清理完一个地方的垃圾后可以继续向右或是向下去清理
其他垃圾。最终运行到(N,M)的位置终止。问:最少需要多少个机器人,能清理完所有的垃圾。
思路:
图中没有给N和M的大小,只是给出了垃圾的位置。输入用0 0表示一组数据输入结束。建一个结构
体来存储垃圾的坐标值。现在来建一个二分图,图的两边就是垃圾的节点,遍历原图,如果垃圾j在
垃圾i的右下角,就将(i,j)加入到二分图中,最后问题就变为了:求该二分图的最小路径覆盖。由二
分图最小路径覆盖 = 点数 - 二分图最大匹配,根据匈牙利算法求出二分图最大匹配,然后得出结果。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int MAXN = 600; struct Node { int x; int y; }Point[MAXN]; bool Map[MAXN][MAXN],Mask[MAXN]; int NX,NY; int cx[MAXN],cy[MAXN]; int FindPath(int u) { for(int i = 0; i < NY; ++i) { if(Map[u][i] && !Mask[i]) { Mask[i] = 1; if(cy[i] == -1 || FindPath(cy[i])) { cy[i] = u; cx[u] = i; return 1; } } } return 0; } int MaxMatch() { for(int i = 0; i < NX; ++i) cx[i] = -1; for(int i = 0; i < NY; ++i) cy[i] = -1; int res = 0; for(int i = 0; i < NX; ++i) { if(cx[i] == -1) { for(int j = 0; j < NY; ++j) Mask[j] = 0; res += FindPath(i); } } return res; } int main() { int id = 0; while(scanf("%d%d",&Point[id].x,&Point[id].y) && (Point[id].x!=-1 && Point[id].y!=-1)) { id++; while(scanf("%d%d",&Point[id].x,&Point[id].y) && (Point[id].x||Point[id].y)) id++; memset(Map,0,sizeof(Map)); for(int i = 0; i < id; ++i) { for(int j = i+1; j < id; ++j) { if(Point[i].x <= Point[j].x && Point[i].y <= Point[j].y) Map[i][j] = 1; else if(Point[i].x >= Point[j].x && Point[i].y >= Point[j].y) Map[j][i] = 1; } } NX = NY = id; printf("%d\n",id-MaxMatch()); id = 0; } return 0; }
标签:
原文地址:http://blog.csdn.net/lianai911/article/details/44925251