题目链接:https://www.cometoj.com/problem/1642
注意枚举时的技巧与细节
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1005;
int n, m;
bool vis[maxn];
struct node{
ll id, cost; //id: 第几个宝物
};
bool cmp(node n1, node n2)
{
return n1.cost < n2.cost;
}
vector<node> all; //所有宝物对应的id与cost (单集合)
vector<node> man[maxn]; //编号为i的人的宝物集合 (分开的子集, 将上面的集合分组)
int main()
{
cin >> n >> m;
int a, b;
for (int i = 1; i <= m; i++)
{
cin >> a >> b;
all.push_back({i, a});
man[b].push_back({i, a});
}
/*两类集合分别排序*/
sort(all.begin(), all.end(), cmp);
for (int i = 1; i <= n; i++)
sort(man[i].begin(), man[i].end(), cmp);
/*枚举所有情况*/
ll maxc = 1e18;
for (ll k = 1; k <= m; k++) //使所有高度都少于k
{
ll ans = 0, cnt = 0; //分别记录费用和数目
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; i++)
if(man[i].size() >= k)
for (int j = 0; j <= man[i].size() - k; j++)
{
ans += man[i][j].cost; //记录已花费宝物费用
cnt++; //记录已买宝物数
vis[man[i][j].id] = true; //表示的i个宝物已买
}
for (ll i = 0; i < all.size() && cnt < k; i++) //如果此时买的宝物数还不是最多, 在从最小的价格买
if(!vis[all[i].id])
ans += all[i].cost, cnt++;
maxc = min(maxc, ans);
}
cout << maxc << endl;
return 0;
}