Asteroids

来源:互联网 发布:character mysql 编辑:程序博客网 时间:2024/06/05 10:10

Description
Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at the lattice points of the grid.

Fortunately, Bessie has a powerful weapon that can vaporize all the asteroids in any given row or column of the grid with a single shot.This weapon is quite expensive, so she wishes to use it sparingly.Given the location of all the asteroids in the field, find the minimum number of shots Bessie needs to fire to eliminate all of the asteroids.

Input
* Line 1: Two integers N and K, separated by a single space.

Output
* Line 1: The integer representing the minimum number of times Bessie must shoot.

Sample Input
3 4
1 1
1 3
2 2
3 2

Sample Output
2

Hint
INPUT DETAILS:
The following diagram represents the data, where “X” is an asteroid and “.” is empty space:
X.X
.X.
.X.

OUTPUT DETAILS:
Bessie may fire across row 1 to destroy the asteroids at (1,1) and (1,3), and then she may fire down column 2 to destroy the asteroids at (2,2) and (3,2).

题目大意
在N*N的网格中有k颗小行星。小行星i的位置是(Ri,Ci)。现在有一个强力武器能够用一发光束将一整行或一整列的小行星轰为灰烬。想要利用这个武器摧毁所有的小行星最少需要激几发光束?

解题思路
这个题最重要的地方在建图上。图建好后,用一个简单的匈牙利算法即可解决问题。
要破坏某个小行星,只能通过对应水平方向或竖直方向的光束的攻击。利用攻击方法只有两种这一点,可以将该问题转化为图。把光束当做图的顶点,而把小行星当做连接对应光束的边。这样转换之后,光束的攻击方案即对应一个顶点集合S,而要求攻击方案能够摧毁所有的小行星,也就是图中的每条边都至少有一个属于S的顶点。这样一来,问题就转为了求最小的满足上述要求的顶点集合S。这正是最小顶点覆盖的问题。在二分图中,最小顶点覆盖等于最大匹配。所以在本题中,所有顶点可以分成水平方向和竖直方向的攻击选择两类,而每颗小行星所对应的边都分别与一个水平方向和一个竖直方向的顶点相连,所以是二分图。
二分图建好后,使用匈牙利算法求最大匹配。
代码如下:

#include<iostream>#include<memory.h>using namespace std;int map[505][505];int vis[505];int result[505];int n,k,ans;bool find(int a);int main(){    int i,j,r,c;    while(cin>>n>>k)    {        memset(map,0,sizeof(map));        memset(result,-1,sizeof(result));        ans=0;        for(i=0;i<k;i++)        {            cin>>r>>c;            map[r][c]=1;        }        for(i=1;i<=n;i++)        {            memset(vis,0,sizeof(vis));            if(find(i))            ans++;        }        cout<<ans<<endl;    }    return 0;}bool find(int a){    int i;    for(i=1;i<=n;i++)    {        if(map[a][i]&&!vis[i])        {            vis[i]=true;            if(result[i]==-1||find(result[i]))            {                result[i]=a;                return true;            }        }    }    return false;}
原创粉丝点击