BZOJ 1110: [POI2007]砝码Odw

看了题解,发现是用进制转换来做。这种题不看题解谁会想到用进制转换这种冷门东西???
知道是进制转换就很容易了,就变成了一道贪心+模拟题。
首先,进制是a[1],a[2],a[3],…a[n],然后将所有容器体积都加入,可以得到一个(会变的)进制数:xxxxxxx…xxxxx。
考虑到只需要求有几个砝码能够被装下,而不用求利用率,所以是道贪心,从小到大进行放置显然优秀。于是我们就从小到大放置砝码,这在程序上体现就是不停地将这个(会变的)进制数减小,如果某一位变为了0,那么就向比它高的位借位;如果到某一个砝码减不下去了,就说明放置的砝码数量达到最大了。
这也就是为什么砝码重量一定是整数倍的原因了,如果不是整数倍,借位的时候的余数是不能处理的,有可能几次下来余数的总和又可以放置一个新的砝码了,所以不能忽略;而如果不忽略的话,又该如何处理呢?所以如果要用进制转换来做,就需要砝码重量是整数倍。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,tot,ans;
int a[N],b[N],c[N],bb[N],f[N];
int main(){
	scanf("%d%d",&n,&m);
	for (register int i=1; i<=n; ++i) scanf("%d",&a[i]);
	for (register int i=1; i<=m; ++i) scanf("%d",&b[i]),bb[i]=b[i];
	sort(b+1,b+m+1);
	tot=unique(b+1,b+m+1)-b-1;
	for (register int i=1; i<=n; ++i)
	{
		int x=a[i];
		for (register int j=tot; j>=1; --j)
		{
			f[j]+=x/b[j];
			x%=b[j];
		}
	}
	for (register int i=1; i<=tot; ++i) c[i]=b[i];
	for (register int i=1; i<=m; ++i) b[i]=bb[i];
	sort(b+1,b+m+1);

	for (register int i=1; i<=m; ++i)
	{
		int j=1;
		while ((c[j]<b[i] || !f[j]) && j<=tot) j++;
		if (j==tot+1) {printf("%d\n",ans); return 0;}
		while (c[j]>b[i] && j>=1) f[j]--,f[j-1]+=c[j]/c[j-1],j--;
		f[j]--;
		ans++;
	}
	printf("%d\n",ans); 
return 0;
}
发布了64 篇原创文章 · 获赞 29 · 访问量 664

猜你喜欢

转载自blog.csdn.net/Dove_xyh/article/details/104057406