【金凌模拟试题】:地鼠的困境
Time Limit:1000MS Memory Limit:65536K
Total Submit:40 Accepted:16
Description
地鼠家族面临着一个新的威胁——猎食者。
地鼠家族一共有N个地鼠和M个鼠洞,每个都位于不同的(x, y)坐标中。假如有地鼠在发觉危险以后s秒内都没有回到鼠洞里的话,就可能成为老鹰的食物。当然了,一个鼠洞只能拯救一只地鼠的命运,所有地鼠都以相等的速度v移动。地鼠家族需要设计一种策略,使得老鹰来时,易受攻击的地鼠数量最少。
Input
本题有多组数据。第1行为测试数据组数T(T<=50)。
对于每组数据,第一行4个整数n, m, s和v(n, m <= 100)。以后n行为地鼠的坐标,以后m行为鼠洞的坐标。距离的单位是m,时间的单位是s,速度的单位是m/s。
Output
对于每组数据输出一行,为易受攻击的地鼠的数量。
Sample Input
1
2 2 5 10
1.0 1.0
2.0 2.0
100.0 100.0
20.0 20.0
Sample Output
1
二分图的最大匹配
#include <iostream> using namespace std; double dist(double x1,double y1,double x2,double y2){return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);} const double eps=1e-12;//NOTES:eps #define MAXN 105 #define MAXM 105 struct node { double x; double y; }gopher[MAXN],hole[MAXM]; int n, m; //n为集合x个数,m为集合y个数 bool graph[MAXN][MAXM]; int match[MAXM];//表示元素j的与之匹配的是哪个元素i,一开始要全部初始化为n,表示和哪个都不匹配 int chk[MAXM]; //表示元素i在dfs中是否被访问过 bool dfs(int p) //DFS,从元素p出发寻找增广路 { int i, t; for (i = 1; i <= m; i++) { if (graph[p][i] && !chk[i]) //令i匹配p,递归搜索 { chk[i] = 1; t = match[i]; if (t == -1 || dfs(t)) { match[i] = p; return true; } } } return false; } int hungary() //匈牙利算法,返回最大匹配数 { int i, res = 0; for (i = 1; i <= m; i++) { match[i] = -1; } for (i = 1; i <= n; i++) //循环n次,每次确定一个元素被匹配 { memset(chk,false,sizeof(chk)); if (dfs(i)) //如果找到,匹配数加1 res++; } return res; } int main() { int i, j, s, v,t; double dd; cin>>t; while(t--){ scanf("%d%d%d%d",&n,&m,&s,&v); memset(graph,false,sizeof(graph)); //注意初始化! dd = s*v*s*v; for (i = 1; i <= n; i++) { scanf("%lf%lf",&gopher[i].x,&gopher[i].y); } for (i = 1; i <= m; i++) { scanf("%lf%lf",&hole[i].x,&hole[i].y); } for (i = 1; i <= n; i++) { for (j = 1; j <= m; j++) { if (dist(gopher[i].x,gopher[i].y,hole[j].x,hole[j].y) <= dd) { graph[i][j] = true; } } } printf("%d\n",n - hungary()); } return 0; }