【BZOJ1110】[POI2007]砝码Odw 贪心

【BZOJ1110】[POI2007]砝码Odw

Description

  在byteotian公司搬家的时候,他们发现他们的大量的精密砝码的搬运是一件恼人的工作。公司有一些固定容量的容器可以装这些砝码。他们想装尽量多的砝码以便搬运,并且丢弃剩下的砝码。每个容器可以装的砝码数量有限制,但是他们能够装的总重量不能超过每个容器的限制。一个容器也可以不装任何东西。任何两个砝码都有一个特征,他们的中总有一个的重量是另外一个的整数倍,当然他们也可能相等。

Input

  第一行包含两个数n和m。表示容器的数量以及砝码的数量。(1<=n, m<=100000) 第二行包含n个整数wi,表示每个容器能够装的最大质量。(1<=wi<=1000000000) 第三行包含m个整数mj,表示每个砝码的质量。(1<=mj<=1000000000)

Output

  仅包含一个数,为能够装进容器的最多的砝码数量。

Sample Input

2 4
13 9
4 12 2 4

Sample Output

3

题解:由于任意两个砝码的质量都存在倍数关系,那么本质不同的砝码最多只有log个。并且我们一定是从小到大贪心的去选。下面是具体做法:

将每种砝码当成一位,然后将所有背包容量按照混合进制的方法拆位,将所有背包的每一位进行不进位的加法,这样就相当于将原来的背包合成了一个新背包。在放入物品时,我们先看当前位是否能-1,如果不能,就到更高的位上去借位即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,len,ans;
int bas[50],w[100010],v[100010],c[50];
int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
int main()
{
	n=rd(),m=rd();
	int i,j;
	for(i=1;i<=n;i++)	w[i]=rd();
	for(i=1;i<=m;i++)	v[i]=rd();
	sort(v+1,v+m+1);
	for(i=1;i<=m;i++)
	{
		if(v[i]>bas[len])	bas[++len]=v[i];
		v[i]=len;
	}
	for(i=1;i<=n;i++)	for(j=len;j;j--)	c[j]+=w[i]/bas[j],w[i]%=bas[j];
	for(i=1;i<=m;i++)
	{
		if(c[v[i]])	c[v[i]]--,ans++;
		else
		{
			for(j=v[i];j<=len;j++)
			{
				if(c[j])
				{
					c[j]--;
					break;
				}
				c[j]=bas[j+1]/bas[j]-1;
			}
			if(j>len)	break;
			else	ans++;
		}
	}
	printf("%d",ans);
	return 0;
}
时间: 2024-08-07 08:40:16

【BZOJ1110】[POI2007]砝码Odw 贪心的相关文章

BZOJ 1110: [POI2007]砝码Odw( 贪心 )

ORZjcvb... 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 100009; 6 7 int N, M, item[maxn], V[maxn]; 8 vector<int> o, cnt, Div; 9 10 int main() { 11 12 cin >> N >> M; 13 for(int i = 0; i < N; i++) 14 sca

BZOJ1110 : [POI2007]砝码Odw

砝码从小到大放最优,二分答案mid,转化为判定前mid小的砝码能否放完. 从大到小考虑砝码,依次扫描每个容器,能放就放. 由于砝码重量都成倍数关系,所以最多只有$O(\log n)$种不同的数字,所以总复杂度为$O(n\log^2n)$. #include<cstdio> #include<algorithm> #define N 100010 int n,m,i,j,k,t,a[N],b[N],c[N],l,r,mid,ans; inline void read(int&

BZOJ 1110: [POI2007]砝码Odw

1110: [POI2007]砝码Odw Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 547  Solved: 296[Submit][Status][Discuss] Description 在byteotian公司搬家的时候,他们发现他们的大量的精密砝码的搬运是一件恼人的工作.公司有一些固定容量的容器可以装这些砝码.他们想装尽量多的砝码以便搬运,并且丢弃剩下的砝码.每个容器可以装的砝码数量有限制,但是他们能够装的总重量不能超过每个容器的限制

【搭楼】做题记录

以后做了题还是在这里写一下,觉得好的再去发题解(感觉无脑发题解意义不大) 也不一定是做了的题,看了没打但觉得不错的也可以发上来 (5.23-5.24 第三次月考被X得相当爽) 5.23 星期六 [贪心]Bzoj4027 HEOI2014 兔子与樱花 要是父亲合并儿子又合并就混乱了.然后发现,反正贡献都是一?能合并就在儿子处合并?贪心. [分块]Bzoj3343 教主的魔法 做之前知道了tag,于是很快就想到了算法.还没打过分块呢,于是先去膜拜了一下别人的代码.自己打出来后各种WA,太晚了没调出来

【整理】最近做的几道数学题

数学题也是有意思 那么总结一下 T1.[Bzoj2751][HAOI2012]容易题 题意 有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些限制即A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,求出所有可能的数列的积的和. 题解 考虑一个式子(...)(...)(...),()内为一些数相加,根据乘法分配律,打开这个式子就是每次从每个括号中选一个元素,再把所有可能选择的结果加起来. 这件事情就是我们题目的设问,于是我们只要算出来每个位置sigma可能的选择

蓝桥杯——说好的进阶之砝码称重(贪心算法)

5个砝码 用天平称重时,我们希望用尽可能少的砝码组合称出尽可能多的重量. 如果只有5个砝码,重量分别是1,3,9,27,81.则它们可以组合称出1到121之间任意整数重量(砝码允许放在左右两个盘中). 本题目要求编程实现:对用户给定的重量,给出砝码组合方案. 例如: 用户输入: 5 程序输出: 9-3-1 用户输入: 19 程序输出: 27-9+1 要求程序输出的组合总是大数在前小数在后. 可以假设用户的输入的数字符合范围1~121. public static void main(String

51nod 1449 砝码称重(贪心算法)

题目:传送门. 题意:中文题. 题解:左物右码,w进制.m%w==0||m%w==1||m%w==w-1都是可以的,否则是NO. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; int main() { //左物右码 开始把物品放在左边 long long w,m;

[POI2007]ODW-Weights(贪心)

在byteotian公司搬家的时候,他们发现他们的大量的精密砝码的搬运是一件恼人的工作.公司有一些固定容量的容器可以装这些砝码.他们想装尽量多的砝码以便搬运,并且丢弃剩下的砝码.每个容器可以装的砝码数量有限制,但是他们能够装的总重量不能超过每个容器的限制.一个容器也可以不装任何东西.任何两个砝码都有一个特征,他们的中总有一个的重量是另外一个的整数倍,当然他们也可能相等. Solution 关键的地方就是任意两个物品之间都是整数倍之间的关系. 我们可以吧每个容器k进制拆分,那么我们把物品从小到大依

1449 砝码称重

1449 砝码称重 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 现在有好多种砝码,他们的重量是 w0,w1,w2,...  每种各一个.问用这些砝码能不能表示一个重量为m的东西. 样例解释:可以将重物和3放到一个托盘中,9和1放到另外一个托盘中. Input 单组测试数据. 第一行有两个整数w,m (2 ≤ w ≤ 10^9, 1 ≤ m ≤ 10^9). Output 如果能,输出YES,否则输出NO. Input示例