练习时出现问题的题目总结----贪心(1)


一:

装箱问题

总时间限制: 1000ms 内存限制: 65536kb
描述
一个工厂制造的产品形状都是长方体,它们的高度都是h,长和宽都相等,一共有六个型号,他们的长宽分别为1·1, 2·2, 3·3, 4·4, 5·5, 6·6。这些产品通常使用一个 6·6·h 的长方体包裹包装然后邮寄给客户。因为邮费很贵,所以工厂要想方设法的减小每个订单运送时的包裹数量。他们很需要有一个好的程序帮他们解决这个问题从而节省费用。现在这个程序由你来设计。
输入
输入文件包括几行,每一行代表一个订单。每个订单里的一行包括六个整数,中间用空格隔开,分别为1·1至6·6这六种产品的数量。输入文件将以6个0组成的一行结尾。
输出
除了输入的最后一行6个0以外,输入文件里每一行对应着输出文件的一行,每一行输出一个整数代表对应的订单所需的最小包裹数。
样例输入
0 0 4 0 0 1
7 5 1 0 0 0
0 0 0 0 0 0
样例输出
2
1

思路
刚开始做这个题的时候想的是6单独占一个箱子,1和5放在一个箱子里,4和2放在一个箱子里,3自己放在箱子里;然后又考虑了一下1也是可以放在2的空间的,就出来正解了。
正解:
6的需要单独开一个箱子,5·5也需要开一个箱子并留下装11个1产品的空间,4的需要开一个箱子且留下5个2的空间;3的有些特殊,4个3的正好能装满一个箱子,如果3的数量不是4的倍数,就需要令开箱子来装剩下的,余1的时候箱子还可以装下5个2和6个1的,余2可以装3个2和6个1,余3则可以装1个2还有5个1;对于2的数目大于剩余的空间就还需要再开箱子,然后再计算1的;如果2的数量小于所剩的空间,那么装完后剩下的2的空间就可以转化为1的空间进行计算
代码实现

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
	int a, b, c, d, e, f;
	while (cin >> a >> b >> c >> d >> e >> f)
	{
		if (a ==0&& b == 0&&c ==0&& d ==0&& e ==0&& f == 0)break;
		int ans = 0;//箱子数
		int v2=0;//剩余2*2的空间
		int v1 = 0;//剩余1*1的空间
		int x[4] = { 0,5,3,1 };//存3*3的剩下的2*2空间
		ans = d + e + f + ceil(c*1.0 / 4);
		v2 = d * 5 + x[c % 4];
		if (b > v2)
			ans += ceil((b - v2)*1.0 / 9);
		v1 = 36 * (ans - f) - 25 * e - 16 * d - 9 * c - 4 * b;
		if (a > v1)
			ans += ceil((a - v1)*1.0 / 36);
		cout << ans << endl;
	}
	return 0;
}

做题时遇到的问题:

ceil函数
ceil()函数是向上取整的函数,()内的是一个浮点型的数值;与其相对应的是向下取整函数floor(),用法相似。
头文件:cmath

做题时没注意()内的数值应该是浮点型的,在这个点上就卡了很久

二:

Ride to Office

总时间限制: 1000ms 内存限制: 65536kB
描述
Many staff of are living in a place called MZone, far from their office( 4.5 km ). Due to the bad traffic, many staff choose to ride a bike.

We may assume that all the people except “Weiwei” ride from home to office at a fixed speed. Weiwei is a people with a different riding habit – he always tries to follow another rider to avoid riding alone. When Weiwei gets to the gate of MZone, he will look for someone who is setting off to the Office. If he finds someone, he will follow that rider, or if not, he will wait for someone to follow. On the way from his home to office, at any time if a faster student surpassed Weiwei, he will leave the rider he is following and speed up to follow the faster one.

We assume the time that Weiwei gets to the gate of MZone is zero. Given the set off time and speed of the other people, your task is to give the time when Weiwei arrives at his office.
输入
There are several test cases. The first line of each case is N (1 <= N <= 10000) representing the number of riders (excluding Weiwei). N = 0 ends the input. The following N lines are information of N different riders, in such format:

Vi [TAB] Ti

Vi is a positive integer <= 40, indicating the speed of the i-th rider (kph, kilometers per hour). Ti is the set off time of the i-th rider, which is an integer and counted in seconds. In any case it is assured that there always exists a nonnegative Ti.
输出
Output one line for each case: the arrival time of Weiwei. Round up (ceiling) the value when dealing with a fraction.
样例输入
4
20 0
25 -155
27 190
30 240
2
21 0
22 34
0
样例输出
780
771

题意描述:
起点与终点相隔4500米。现威威需要从起点骑车到终点。但是,他有个习惯,沿途需要有人陪伴,即以相同的速度,与另外一个人一起骑。而当他遇到以更快的速度骑车的人时,他会以相应的速度跟上这个更快的人。先给定所有与Charley同路的人各自的速度与出发时间,问威威以这种方式跟人,骑完4500米需要多少时间。得出的结果若是小数,则向上取整。

解题思路:
最开始的想法就是威威一定是跟着最快的人到达终点,结果t<0的卡了好久,最后突然发现没有什么影响完全可以不考虑。
正解:
威威是从零时刻出发的,对于在威威之前出发的人,如果他一直都在威威的前边,那么威威永远也追不上他;如果他被威威追上了,那说明威威的速度要比他快,威威也不会跟着他走,
所以我们不用考虑提前出发即t<0的人。
仔细分析我们会发现威威一定会跟着最快的人前进,那么他就会和最快的人一起到达终点,即最后的时间是相等的,那么我们们就将这个题转化为求最快的人到达的时间。

代码实现:

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
	int n;
	double v, t;
	while (cin >> n)
	{
		double ans = 100000;
		if (n == 0)
			break;
		for (int i = 0; i < n; i++)
		{
			cin >> v >> t;
			if (t < 0)//不考虑t<0
				continue;
			t = 4500*3.6/ v + t;
			if (ans > t)
				ans = t;//求所用时间的最小值
		}
		cout << ceil(ans) << endl;
	}
	return 0;
}

做题时出现的问题:

因为这道题已经做过一次了,所以思路出的比较快,程序调好了之后,在oj上交了好几次都不能通过,然后我就又去一本通上提交了一次结果通过了…然后研究了半天感觉可能是我之前的算式精度的问题,把算式改了一下再去提交就通过了
这是我以前从来没考虑过的问题,经过这一次的错误,以后做题时应该考虑这方面的问题

最小新整数

总时间限制: 1000ms 内存限制: 65536kB
描述
给定一个十进制正整数n(0 < n < 1000000000),每个数位上数字均不为0。n的位数为m。
现在从m位中删除k位(0<k < m),求生成的新整数最小为多少?
例如: n = 9128456, k = 2, 则生成的新整数最小为12456

输入
第一行t, 表示有t组数据;
接下来t行,每一行表示一组测试数据,每组测试数据包含两个数字n, k。
输出
t行,每行一个数字,表示从n中删除k位后得到的最小整数。
样例输入
2
9128456 2
1444 3
样例输出
12456
1

解题思路:
最开始的想法是删去最大的数,然后自己写了一串数字试了试发现不对,想了想应该是删除高位中的大数才对。
这道题的正解应该是删除一部分序列中的最大值,比如样例中的9的位数比1高而且9>1,8的位数比4高且8>4;
输入的数字是从高位向低位排列的,那么从前往后遍历即可
代码实现:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
	int t;
	char a[11];
	int k;
	cin >> t;
	while(t--)
	{
		cin >> a >> k;
		int m = strlen(a);
		while (k--)//循环k遍
		{
			for (int i = 0; i < m-1; i++)
			{
				if (a[i] > a[i+1])
				{
					for (int j = i; j < m - 1; j++)//删除a[I]
						a[j] = a[j + 1];
					break;
				}
			}
			m--;
		}
		for(int i=0;i<m;i++)
		cout << a[i] ;
		cout << endl;
	}
	return 0;
}

解题出现的问题:
1.刚开始没有好好读题,理解错了题意,就直接傻傻的把数组排序然后就直接删除了后k位,提交了一次发现错了之后又好好看了看题目发现理解错了…然后又想了半天才出的正确思路,代码实现也很费劲
2.strlen函数的头文件搞错了…
正解:strlen函数的头文件是cstring

电池的寿命

总时间限制: 1000ms 内存限制: 65536kB
描述
小S新买了一个掌上游戏机,这个游戏机由两节5号电池供电。为了保证能够长时间玩游戏,他买了很多5号电池,这些电池的生产商不同,质量也有差异,因而使用寿命也有所不同,有的能使用5个小时,有的可能就只能使用3个小时。显然如果他只有两个电池一个能用5小时一个能用3小时,那么他只能玩3个小时的游戏,有一个电池剩下的电量无法使用,但是如果他有更多的电池,就可以更加充分地利用它们,比如他有三个电池分别能用3、3、5小时,他可以先使用两节能用3个小时的电池,使用半个小时后再把其中一个换成能使用5个小时的电池,两个半小时后再把剩下的一节电池换成刚才换下的电池(那个电池还能用2.5个小时),这样总共就可以使用5.5个小时,没有一点浪费。

现在已知电池的数量和电池能够使用的时间,请你找一种方案使得使用时间尽可能的长。

输入
输入包含多组数据。每组数据包括两行,第一行是一个整数N (2 ≤ N ≤ 1000),表示电池的数目,接下来一行是N个正整数表示电池能使用的时间。

输出
对每组数据输出一行,表示电池能使用的时间,保留到小数点后1位。

样例输入
2
3 5
3
3 3 5
样例输出
3.0
5.5

思路实现
一开始没有什么思路,看了下样例就有了一点想法,可以说是猜出来的,然后又自己造了两组数据试了一下,发现应该是对的就开始写程序了。
正解:
通过样例分析我们发现由于电池可以拆分使用,故尽量拆成相等两堆,但如果其中一个巨大,剩下的加起来都不足与之抗衡,则不能拆分。所以找出最大的一个,与剩下的电池的电量相比较。
如果容量最大的电池大于剩下的电池的容量和,那么最多能使用剩下的部分的电量,如果小于则平分。

代码实现:

#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
	int n;
	int t;
	int sum, max;
	while (cin >> n)
	{
		sum = 0; max = 0;
		for (int i = 0; i < n; i++)
		{
			cin >> t;
			sum += t;
			if (t > max)max = t;
		}
		if (max >= sum - max)
			cout << fixed << setprecision(1) << (sum - max) * 1.0 << endl;
		else
			cout << fixed << setprecision(1) << sum * 1.0 / 2 << endl;
	}
	return 0;
}

解题时的问题:
代码实现时,有多组样例,但我每次循环时没对max和sum进行重置导致了代码错误,当时还没检查出来;过了一天才看出来错误

发布了19 篇原创文章 · 获赞 24 · 访问量 1980

猜你喜欢

转载自blog.csdn.net/SDAU_LGX/article/details/104794848
今日推荐