暴力搜索
当我们发现 u u u 很小时,就可以直接暴搜。但我们该怎么搜索呢?
因为是教师送给学生礼物,所以我们先搜索老师,记录下来当前这个老师选还是不选。
当我们选完了 p p p 个老师,学生部分就可以直接算分数。
先枚举每一个老师,如果当前老师选上了,就去枚举学生,在当前这个学生的贡献中加上幸福度。
为了使幸福度最大,所以在算完所有学生的贡献后,我们要对 m m m 个贡献进行从大到小的排序,最终在得分中加上前 q q q 个学生的贡献,因为学生就要选 q q q 个。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n, m, p, q, r;
// g: 幸福度,cache: 存学生的贡献
int g[30][30], cache[30];
int a[30]; // 存储每位老师选不选
int ans;
bool cmp(int x, int y) {
return x > y;
}
void calc() {
// 先清空贡献数组
memset(cache, 0, sizeof(cache));
for (int i = 1; i <= n; i++) {
if (a[i]) { // 选这位老师
for (int j = 1; j <= m; j++) { // 遍历学生
cache[j] += g[i][j]; // 第 j 位同学加上 g[i][j] 的幸福度
}
}
}
sort(cache + 1, cache + m + 1, cmp); // 从大到小排序,最终取前 q 个记为得分
int res = 0;
for (int i = 1; i <= q; i++)
res += cache[i];
ans = max(ans, res); // 取最大值
}
void dfs(int x, int w) { // 暴搜,x: 当前选到第几位老师,w: 选了几位老师
// 我们可以把每位老师当做一个编号,这样处理起来就比较方便
if (w > p) return ; // 超过了 p 个老师,不符合要求
if (x == n + 1) { // n + 1 代表第 1 ~ n 位老师都选完了
if (w == p) calc(); // 老师总数 = p,符合要求,计算得分
return ;
}
a[x] = 1; // 选这个老师
dfs(x + 1, w + 1);
a[x] = 0; // 不选这个老师
dfs(x + 1, w);
}
int main() {
scanf("%d%d%d%d%d", &n, &m, &p, &q, &r);
for (int i = 1; i <= r; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
g[x][y] += z; // 记录幸福度
}
dfs(1, 0);
printf("%d\n", ans); // 不要忘了换行
return 0;
}