题目链接:HDU6667
题意:给定n个班级,每个班级人数及制作奶茶数量,每个班只能喝其他班级制作的奶茶,每人一杯,求解最多有多少人可以喝到奶茶。
解题思路:先将人数递减排序,并计算出所有奶茶数,然后从上至下遍历一遍,每个人都先喝后面一个班级的奶茶,奶茶不够则继续使用其后其他班级的,
每个班级能够喝到的最多奶茶数为min(当前班级人数,能被当前班级喝的奶茶数量)
其中
能被当前班级喝的奶茶数量=当前未被喝的奶茶数-当前班级未被喝掉的奶茶数量
而
当前班级未被喝掉的奶茶数量=max(当前班级的奶茶数-之前班级喝掉的当前班级极其后面班级的奶茶,0)
然后
之前班级喝掉的当前班级极其后面班级的奶茶 = 上一个班级喝掉的最多的奶茶数 +max( 上一个班级给上上个班级喝的奶茶后剩余的奶茶数)
这样就能保证每个班级的奶茶不被自己班级使用,并且先被上面班级喝。最后将每个班级能够喝到的最多奶茶数相加即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ms(a) memset(a,0,sizeof(a));
typedef long long ll;
const int maxn = 6e6+10l;
struct node{
ll num;
ll val;
int pos;
};
node a[maxn],b[maxn],c[maxn];
bool cmp1(node x,node y){
return x.num>y.num;
}
int main()
{
int t;
int n;
scanf("%d",&t);
while(t--){
scanf("%d,",&n);
ll sum=0;
for(int i=1;i<=n;i++){
scanf("%lld %lld",&a[i].num,&a[i].val);
a[i].pos=i;
b[i]=a[i];
sum+=a[i].val;
}
sort(b+1,b+1+n,cmp1);
ll ans=0,ret=0;
ll gg=0,kk=0;
for(int i=1;i<=n;i++){
ret=min(b[i].num,sum-max(b[i].val-gg,kk));
if(gg<=b[i].val){
gg=0;
}else{
gg=gg-b[i].val;
}
ans+=ret;
gg+=ret;
sum-=ret;
}
printf("%lld\n",ans);
}
return 0;
}