【POI2007】ODW-Weights【贪心】【进制】

3 篇文章 0 订阅
2 篇文章 0 订阅

传送门

要求装走最多数量而不是最重,,这启示我们从最轻的开始贪心。

我们发现权值太多,又不知道每个东西应该装哪个箱子最优。

认真读题:砝码重量成比例。

成比例,,那就可以除以一个数让它们变小,,那这个数可以视作重量的进制,。所以我们亦可以将箱子表示成进制状态。

那每个箱子被拆分成了不同的进制。最后从小到大走一遍。如果当前没有箱子,我们大可以找个更大的箱子把它拆开。这样做是对的,因为就算我们放弃当前小砝码,那以后还得用那个大箱子最多贡献1.还不如拆成很多个小箱子造福社会。

如果实在没法子,,那就GG。

#include<bits/stdc++.h>
#define int long long
using namespace std;
#define in read()
int in{
	int cnt=0,f=1;char ch=0;
	while(!isdigit(ch)){
		ch=getchar();if(ch=='-')f=-1;
	}
	while(isdigit(ch)){
		cnt=cnt*10+ch-48;
		ch=getchar();
	}return cnt*f;
}
int n,m;
int a[100003],b[100003];
int c[100003],cnt[100003];int tot;
bool have(int now){
	for(int i=now+1;i<=tot;i++){
		if(cnt[i]){
			cnt[i]--;cnt[now]+=c[i]/c[now];return true;
		}
	}return false;
}
signed main(){
	n=in;m=in;for(int i=1;i<=n;i++)a[i]=in;for(int j=1;j<=m;j++)b[j]=in;
	sort(a+1,a+n+1);sort(b+1,b+m+1);
	for(int i=1;i<=m;i++)if(b[i]!=b[i-1])c[++tot]=b[i];
	for(int i=1;i<=n;i++){
		for(int j=tot;j>=1;j--){
			while(a[i]>=c[j]){
				a[i]-=c[j];cnt[j]++;
			}
		}
	}int now=1;
	for(int i=1;i<=m;i++){
		int x=b[i];
		while(x>c[now])++now;
		x=c[now];
		if(cnt[now])cnt[now]--;
		else{
			if(have(now))cnt[now]--;
			else{
				cout<<i-1;return 0;
			}
		}
	}
	cout<<m;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值