题目在:http://poj.org/problem?id=1548
现在练习算法的时候,都是按照分类做的,所以已经知道这个题目可以用最小路径覆盖来解决。所以按照这个方向想想就能把问题转换成最小路径覆盖问题了。
题目比较容易理解,就是说收垃圾的机器人从最左上出发,在格子里沿着右和下漫步整个格子一直到最右下面。在有垃圾的地方收垃圾,没有地方可以跳过。
然后找出最小的机器人数,可以将所有垃圾都收走。
图中有点,点之间按照一个规则可达(从左上到右下的关系),找到一个最小的路径,覆盖所有的点。
恩,其实一下子就会想到最小路径覆盖。
只不过在建图的时候需要一些注意的地方: 如果点B在点A的右下方(包括竖直下 和 横右),就认为从A到B是可达的,建立图的时候是根据垃圾点建图
这个角度来看和 http://poj.org/problem?id=3020 是很相似的。
#include <stdio.h>
#include <memory.h>
#define MAX_NUM 625
#define MAX_GRID 25
int vvAdj[MAX_NUM][MAX_NUM];
int nRow, nCol;
int map[MAX_GRID][MAX_GRID];
bool visit[MAX_NUM];
int matched[MAX_NUM];
int nGabage;
bool dfs(int f)//用dfs求增广路径
{
for( int i = 1; i <= nGabage; i++)
{
if(!visit[i] && vvAdj[f][i])
{
visit[i] = true;
if(matched[i] == -1 || dfs(matched[i]))
{
matched[i] = f;
return true;
}
}
}
return false;
}
int main()
{
int f,t;
int i,j;
int x,y;
while(scanf("%d%d", &f, &t) != EOF)
{
if( f == -1 && t == -1)
{
break;
}
nRow = f;
nCol = t;
memset(matched, -1, sizeof(matched));
memset(map, 0, sizeof(map));
memset(vvAdj, 0, sizeof(vvAdj));
map[f-1][t-1] = 1;
nGabage = 2;
while(scanf("%d%d", &f, &t))//将垃圾在节点图总标号,然后用垃圾点 建立图
{
if(f == 0 && t == 0)
{
break;
}
map[f-1][t-1] = nGabage;
nGabage++;
nRow = nRow > f ? nRow : f;
nCol = nCol > t ? nCol : t;
}
for( i = 0; i < nRow; i++)//用垃圾点建立图
{
for( j = 0; j < nCol; j++)
{
if(map[i][j] != 0)//需找所有到 垃圾 map[i][j]可达的垃圾点
{
for(x = i; x < nRow; x++)
{
for( y = j; y < nCol; y++)
{
if(x == i && y == j)
continue;
if(map[x][y] != 0)
{
vvAdj[map[i][j]][map[x][y]] = 1;
}
}
}
}
}
}
nGabage--;
int nCount = 0;
for(i = 1; i <= nGabage; i++)
{
memset(visit, 0, sizeof(visit));
if(dfs(i))
{
nCount++;
}
}
printf("%d\n", nGabage - nCount);
//create vvadjacent
}
return 0;
}