程序竞赛SDAU--贪心算法(第三周)

瘦欲@ 提交于 2020-03-16 17:51:30

① 假设一个箱子能放下4个 苹果,我有n个苹果需要几个箱子?
总的箱子数:(n+4-1)/4;
②下面的这个题中 还有一个 利用求余数来判断能放几个别的类型

例题:一个工厂制造的产品形状都是长方体,它们的高度都是h,长和宽都相等,一共有六个型号,他们的长宽分别为11, 22, 33, 44, 55, 66。这些产品通常使用一个 66h 的长方体包裹包装然后邮寄给客户。因为邮费很贵,所以工厂要想方设法的减小每个订单运送时的包裹数量。他们很需要有一个好的程序帮他们解决这个问题从而节省费用。现在这个程序由你来设计。
输入
输入文件包括几行,每一行代表一个订单。每个订单里的一行包括六个整数,中间用空格隔开,分别为11至66这六种产品的数量。输入文件将以6个0组成的一行结尾。
输出
除了输入的最后一行6个0以外,输入文件里每一行对应着输出文件的一行,每一行输出一个整数代表对应的订单所需的最小包裹数。
样例输入
0 0 4 0 0 1
7 5 1 0 0 0
0 0 0 0 0 0
样例输出
2
1
原始思路过程:
刚开始的时候我的代码很长,我想的一个箱子放a6不剩空间 放a5剩下11个空
放a4剩下 20个空 这个能放 20个11或者5个11
放a3 情况就多了 放一个 的时候 剩 5个22 或者20个空
放两个剩3个2
2或者12空
放三个 剩1个22或者4个空
先去把大的放完之后剩下的空看看能不能把a2a1全放下不能就再加箱子
但是这样在判断过程中太容易出错了,比如说 我在处理过程中就出现在a3的时候就忘了加个额外的箱子,还有就是我当时还把能放1
1和能放22的空间分开了,他们可是同一块地方,分开不就成了两块了 ,代码长度也到了1000+;
后来问了下别人才知道别人把我的思路的部分简化了
ac思路过程:
把最麻烦的a3过程简化到数组中,如果a3%4==0就说明不剩空间
a3%4= =1 说明剩5个2
2 一下同理
然后就把他们的求余结果当角标就可以了放到chu[]数组里
还有就是在计算剩下的11的空间时,用的是用(箱子数)36-a636-a525-a416-a39-a2*4;这个感觉更简洁,不用再算来算去了
哇 好!

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<string>
using namespace std;
int chu[] = { 0,5,3,1 };
int main()
{
	int  a1, a2, a3, a4, a5, a6;
	while (cin >> a1 >> a2 >> a3 >> a4 >> a5 >> a6)
	{
		if (a1 == 0 && a2 == 0 && a3 == 0 && a4 == 0 && a5 == 0 && a6 == 0)
			return 0;
		int s = 0;
		s = a6 + a5 + a4 + (a3 + 4 - 1) / 4;
		int u2 = a4 * 5 + chu[a3 % 4];
		if (u2 < a2)
			s += (a2 - u2 + 9 - 1) / 9;
		int u1 = s * 36 - a6 * 36 - a5 * 25 - a4 * 16 - a3 * 9 - a2 * 4;
		if (u1 < a1)
		{
			s += (a1 - u1 + 36 - 1) / 36;
		}
		cout << s << endl;
	}
}

①ceil函数的使用 (cmath):返回大于或者等于指定表达式的最小整数
不是四舍五入,只要后边小数!=0 就加1
ceil(2.3)=2;

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
原始思路刚开始理解题意没理解对,把这个问题想成了追击问题了,我先按照时间顺序排序,然后通过前后时间差*速度求路程,然后累加路程==4.5,好蠢啊,没读好题。
ac思路因为它的速度是随着人改变的,可以想象下它最后是怎么到达终点的,是跟着时间最短的人一起到达终点,所以这个题就是考虑谁先到达终点,
因为不管前边的人出发有多早,后边那个不管出发有多么晚,但他只要他速度快,迟早能追上前边的人,那个主人公就跟着它跑了,所以这个题就是判断谁先到达终点的。嘤嘤嘤

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<string>
#include<cmath>
using namespace std;
int main()
{
	int n;
	while (cin >> n && n)
	{
		int k = 99999999;
		int t;	double time =0,v; 
		for (int i = 0; i < n; i++)
		{
			cin >> v >> t;
			if (t < 0) continue;
			time = t + (4500 / v * 3.6);
			time = ceil(time);
			k=k<time?k:time;
		}
		cout << k << endl;
		

	}
}

给出n 个物体,分别给出每个的质量,并且两个物体(假设质量分别为m1,m2)相撞的时候变成一个物体,质量为2sqrt(m1m2),并且只会出现两个两个物品碰撞的情况,问最终能得到的物体的最小质量是多少。

设质量为a, b, c,令a > b > c >,则有:
Ans = sqrt(sqrt(2 * a * b) * c * 2) or
Ans = sqrt(2 * a * sqrt(2 * b * c))
可见在一式中最大数a被两次开根,而二式中只一次开根,那么一式要比二式更优,于是每次选择最大的两个数开根计算,让大数尽量多被开根答案最小.
原始思路
当时看到这个题,我就在想 肯定得大的碰小的,结果小么,但是我没考虑到开根号的问题,如果让大的撞大,那他们不就能多开几次根号么,开完根号值就变小了
但是 等老师讲完思路后,我在想 不就是大碰大,不就完了么,为啥还要用优先队列啊,因为两个球碰完结合成一个球了吧,那他一定会参与下一次的碰撞么、???不一定,每次碰撞都应该是最大和次大的来碰,你总不能碰完一次就sort一次吧,这样就麻烦了。
ac思路让两个大的相碰,之后把碰完的结果再存进队列中,你需要把那俩给pop()掉,,他就会自动排序。然后把碰完的push进去。

const int maxn=110;
struct Node
{
    double val;
    bool operator < (const Node &a)const
    {
	return val<a.val;
    }
};
int n;
priority_queue<Node> q;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
	Node node;
	for(int i=0;i<n;i++)
	{
	    double val;
	    scanf("%lf",&val);
	    node.val=val;
	    q.push(node);
	}
	for(int i=1;i<n;i++)
	{
	    double a=q.top().val;
	    q.pop();
	    double b=q.top().val;
	    q.pop();
	    node.val=2*sqrt(a*b);
	    q.push(node);
	}
	printf("%.3f\n",q.top().val);
	q.pop();
    }
    return 0;
}
}

①不按照题目方向来思考问题,找它的反面来做题

题意:有m个人,每人得到n张牌,牌的号码是1到n*m之间的任意n个数,每张牌都只有一张,问我至少能赢多少局。
Sample Input
2 5
1 7 2 10 9
6 11
62 63 54 66 65 61 57 56 50 53 48
0 0
Sample Output
Case 1: 2
Case 2: 4

思路:可以转化为你最多输max次,那么至少赢n-max次 而最多输max次,则是对方最多赢max次,则用对方的最小的牌去依次比较你手中的牌(按照升序排),如果找到有比它小的,则对方赢一次 依次循环直到遍历完对方的牌。

**感觉这个思想经常用但是不是经常想到,没去直接想过这个问题都是在分析题,如果这个题能按着方法做下去,基本上就不去想别得了。

感想:这种还是进行贪心学习,贪心的题目我还没有做完,感觉一些英文题啊读不懂,一些题也不知道怎么下手,就像老师说的没有思路就多花时间想想,等我做完这些贪心我会再对那些题目进行分析总结的。贪心的课件最后那几个题自己没理解好,感觉要考虑的东西越来越多了。还要自己下功夫!**

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!