本专栏持续输出数据结构题目集,欢迎订阅。
题目
在 520 这个日子里,没有比开发一个约会 App 更合适做的事情了。这个软件的需求很简单,用户输入自己的性别、想要约会的异性的年龄范围 [a,b]、身高范围 [c,d],你要帮所有用户匹配出系统中满足其约会条件的异性。注意:双方性别、年龄、身高的要求必须全都符合对方的要求才可以;每人最多只能匹配一位异性。
当然,同时让每个人都满意的目标其实很难达到,你只要尽力配成最多对就可以了。
输入格式:
输入第 1 行给出正整数 n (≤500) ,为系统中登记的用户人数。随后 n 行,每行给出一位用户的信息,格式如下:
性别 年龄 身高 a b c d
其中 性别 为 0 表示女性,1 表示男性,是该用户自己的性别;年龄 和 身高 也是用户自己的信息,均为不超过 200 的正整数;后面四个数字依次表示该用户想要约会的异性的年龄下限、年龄上限、身高下限、身高上限 —— 注意这里的范围都是闭区间,数字均为不超过 200 的正整数。同行数字间以 1 个空格分隔。
输出格式:
在一行中输出能够同时成功配对的最大对数。
输入样例:
7
0 23 165 23 35 170 180
1 25 178 22 25 160 170
0 25 175 26 40 180 190
1 38 184 22 36 170 180
1 28 180 20 30 165 175
0 36 172 36 40 180 190
1 37 181 25 36 172 175
输出样例:
3
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_USERS 500
// 用户信息结构体
typedef struct {
int gender; // 0:女性, 1:男性
int age; // 年龄
int height; // 身高
int a, b; // 期望异性年龄范围[a,b]
int c, d; // 期望异性身高范围[c,d]
} User;
// 全局变量
User users[MAX_USERS]; // 存储所有用户信息
int graph[MAX_USERS][MAX_USERS]; // 二分图邻接矩阵
int match[MAX_USERS]; // 记录匹配关系
int visited[MAX_USERS]; // DFS访问标记
int n; // 用户总数
// 检查两个用户是否互相满足条件
int isMatch(int u, int v) {
// 检查性别是否为异性
if (users[u].gender == users[v].gender) {
return 0;
}
// u满足v的要求
int u_ok = (users[u].age >= users[v].a) && (users[u].age <= users[v].b) &&
(users[u].height >= users[v].c) && (users[u].height <= users[v].d);
// v满足u的要求
int v_ok = (users[v].age >= users[u].a) && (users[v].age <= users[u].b) &&
(users[v].height >= users[u].c) && (users[v].height <= users[u].d);
return u_ok && v_ok;
}
// 匈牙利算法核心:DFS寻找增广路径
int dfs(int u) {
// 遍历所有可能的异性用户
for (int v = 0; v < n; v++) {
// 如果u和v匹配,且v未被访问过
if (graph[u][v] && !visited[v]) {
visited[v] = 1;
// 如果v未匹配,或v的匹配对象可以找到其他匹配
if (match[v] == -1 || dfs(match[v])) {
match[v] = u;
return 1;
}
}
}
return 0;
}
// 计算最大匹配数
int maxMatching() {
int result = 0;
memset(match, -1, sizeof(match)); // 初始化匹配关系为-1(未匹配)
// 对每一位女性用户尝试匹配
for (int u = 0; u < n; u++) {
if (users[u].gender == 0) { // 只处理女性作为左侧节点
memset(visited, 0, sizeof(visited));
if (dfs(u)) {
result++;
}
}
}
return result;
}
int main() {
scanf("%d", &n);
// 读取所有用户信息
for (int i = 0; i < n; i++) {
scanf("%d %d %d %d %d %d %d",
&users[i].gender, &users[i].age, &users[i].height,
&users[i].a, &users[i].b, &users[i].c, &users[i].d);
}
// 构建二分图:女性->男性的有向边
memset(graph, 0, sizeof(graph));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// 只考虑女性对男性的匹配
if (users[i].gender == 0 && users[j].gender == 1) {
if (isMatch(i, j)) {
graph[i][j] = 1;
}
}
}
}
// 计算并输出最大匹配数
printf("%d\n", maxMatching());
return 0;
}
1372

被折叠的 条评论
为什么被折叠?



