分类:枚举 贪心
传送门:夺宝奇兵https://www.zhixincode.com/contest/1/problem/J?problem_id=21
类似题目:codeforce#round div2 C.Election
##思路##
1.为什么要用vector,而不直接用数组呢?
因为每个人的每个物品,他的价值不一样,不可以随便拿来++ –
我们还有根据这个人的物品大小,从小到大的拿,用vector便于排序
2.那么什么时候要拿呢?
我们要拿走 比我们手中的个数多的人的物品,
如果还不够的话,剩余数量从全局从小到大的拿
(以上1.2. 就是在贪心的拿物品)
3.可是我们怎么知道最优的结果是什么???
那我们就枚举,我手中有i个物品时的情况。
这样,我们就可以得到我手中 拿着各种个数时,最优的情况;这些情况下最优的就是全局最优的了
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1005;
struct node
{
ll id,cost;
};
int cmp(node a ,node b)
{
return a.cost<b.cost;
}
vector<node>all;
vector<node>man[maxn];
int vis[maxn];
int n,m;
int main()
{
cin>>n>>m;
int a,b;
for(int i=0;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 maxx=1e15;
//枚举所有情况
for(ll k=1;k<=m;k++)
{
ll ans=0,num=0;
memset(vis,0,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;
num++;
vis[man[i][j].id]=1;
}
}
}
for(ll i=0;i<all.size() && num<k ;i++)
{
if(!vis[all[i].id])
{
ans+=all[i].cost;
num++;
}
}
maxx=min(maxx,ans);
}
cout<<maxx<<endl;
}