算法笔记 4.4 codeup课后习题 贪心

问题 A: 看电视

时间限制: 1 Sec  内存限制: 32 MB

题目描述

暑假到了,小明终于可以开心的看电视了。但是小明喜欢的节目太多了,他希望尽量多的看到完整的节目。
现在他把他喜欢的电视节目的转播时间表给你,你能帮他合理安排吗?

输入

输入包含多组测试数据。每组输入的第一行是一个整数n(n<=100),表示小明喜欢的节目的总数。
接下来n行,每行输入两个整数si和ei(1<=i<=n),表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。
当n=0时,输入结束。

输出

对于每组输入,输出能完整看到的电视节目的个数。

样例输入

12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0

样例输出

5

典型的区间贪心问题

代码:

#include<iostream>		
#include<algorithm> 
using namespace std;
struct TV
{
	int s,e;//起始结束时间
}tv[110];

bool cmp(TV a,TV b){
	if(a.s!=b.s) return a.s>b.s;
	return a.e<b.e;
}
int main(){
	int n;
	while(cin>>n&&n!=0){
		for(int i=0;i<n;i++){
			cin>>tv[i].s>>tv[i].e;
		}
		sort(tv,tv+n,cmp);
		int ans=1,lasts=tv[0].s;
		for(int i=1;i<n;i++){
			if(tv[i].e<=lasts){
				lasts=tv[i].s;
				ans++;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

问题 B: 出租车费

时间限制: 1 Sec  内存限制: 32 MB

题目描述

某市出租车计价规则如下:起步4公里10元,即使你的行程没超过4公里;接下来的4公里,每公里2元;之后每公里2.4元。行程的最后一段即使不到1公里,也当作1公里计费。
一个乘客可以根据行程公里数合理安排坐车方式来使自己的打车费最小。
例如,整个行程为16公里,乘客应该将行程分成长度相同的两部分,每部分花费18元,总共花费36元。如果坐出租车一次走完全程要花费37.2元。
现在给你整个行程的公里数,请你计算坐出租车的最小花费。

输入

输入包含多组测试数据。每组输入一个正整数n(n<10000000),表示整个行程的公里数。
当n=0时,输入结束。

输出

对于每组输入,输出最小花费。如果需要的话,保留一位小数。

样例输入

3
9
16
0

样例输出

10
20.4
36

注意:cout输出 数字大了会自动转换为科学计数法 而有时题目并不允许用科学计数法表示,导致一直答案错误。。。改用printf才行

代码:

#include<iostream>
#include<cmath>
using namespace std;
int main(){	double n;
	while(cin>>n&&n!=0){
		double sum=0;
		if(n<=4){
			sum=10;
		}else if(n<=8){
			sum=10+2*ceil(n-4);
		}else{
			int x1=floor(n/8)*8;
			sum=x1*2.25;
			//接下来6公里时从头坐平均费用2.333<2.4  7公里平均2.285<2.4 
			int x2=ceil(n-x1);
			if(x2==8) sum+=18;
			else if(x2==7) sum+=16;
			else if(x2==6) sum+=14;
			else sum+=2.4*x2;
		}
		if(sum-int(sum)!=0)
			printf("%.1f\n",sum);
		else printf("%.0f\n",sum);
		//用cout大了会自动用科学计数法 而题目为让用科学计数法 所以一直错误 最好用printf()
	}
	return 0;
}

问题 C: To Fill or Not to Fill

时间限制: 1 Sec  内存限制: 32 MB

题目描述

With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.

输入

Each input file contains one test case. For each case, the first line contains 4 positive numbers: Cmax (<= 100), the maximum capacity of the tank; D (<=30000), the distance between Hangzhou and the destination city; Davg (<=20), the average distance per unit gas that the car can run; and N (<= 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: Pi, the unit gas price, and Di (<=D), the distance between this station and Hangzhou, for i=1,...N. All the numbers in a line are separated by a space.

输出

For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print "The maximum travel distance = X" where X is the maximum possible distance the car can run, accurate up to 2 decimal places.

样例输入

59 525 19 2
3.00 314
3.00 0

样例输出

82.89

提示

该题目所要解决的问题是:给定若干加油站信息,问能否驾驶汽车行驶一定的距离。如果能够行驶完全程,则计算最小花费。若不能行驶完全程,则最远能够行驶多长距离。

拿到这一题,首先判断汽车是否能够行驶到终点。什么情况下汽车无法行驶到终点呢?两种情况:起点根本就没有加油站,汽车无法启动;或者中途两个加油站之间的距离大于加满油后汽车能够行驶的最大距离。前者汽车行驶的最大距离为0.00,而后者最大距离为当前加油站的距离加上在这个加油站加满油后能够行驶的最大距离。在这里,需要将加油站按到杭州的距离从小到大排序。

接下来在能够行驶到终点的情况下计算最小花费。我们首先从路程来考虑,如果在路上,我们能够使用最便宜的汽油,当然就在那个加油站加油了。所以从起点开始遍历每个加油站。假设遍历到了第i个加油站,我们现在来判断在加油站i应该加多少油。设当前汽车离杭州的距离为curLen,当前加油站离杭州的距离为nodes[i].dis,加满油以后汽车能够行驶的最大距离为(dis=cmax*len)。这样就有node[i].dis <= curLen <= nodes[i].dis+dis,否则的话第i个加油站的油是不起作用的。于是在第i个加油站的作用范围内寻找有没有更为便宜的加油站,如果有,则下次使用这个加油站的油(j),这次汽车应该行驶到这个加油站,即touch=nodes[j].dis。如果没有找到更为便宜的加油站则可以在第i个加油站加满油,即touch=nodes[i].dis+dis。然后判断下次应该行驶到的距离与当前距离的关系,如果下次应当行驶到的距离大于当前距离,则汽车行驶,否则不动(也就是说上个加油站的油更便宜,后一个加油站也便宜,根本就不需要在当前加油站加油)。

 

注意1:一路向前,不存在后退,公路上行走的轨迹长度为路程,高速公路每隔一点路程就有加油站,但看你怎么加
注意2:加油的价格=要加跑的距离/len*price

算法思路:
	在自己的范围内遍历所有价格:
		若自己的油价最低
			若能直接到达终点 
				加油到终点即可
			若不能直接到终点
				加满
			
			在自己范围内找到油价次低的
				(油满状态下)开到油价次低的站点(有余油)
			
		若自己的油价不是最低
			找自己范围内离自己最近的比自己便宜的站点B
			若余油能跑到B站点
				跑到B站点(更新余油)
			若余油不能跑到B站点
				加油到能跑到B站点即可(余油变为0)
			

代码:

#include<iostream>		
#include<algorithm> 
#include<cmath>
using namespace std;
struct gas
{
	double price;
	double distance;	
}Gas[510];
bool cmp(gas a,gas b){
	if(a.distance!=b.distance) return a.distance<b.distance;//同一个地方应该不会有两个加油站 但还是写了
	return a.price<b.price;
}
int main(){
	double C,D,len;
	int N;
	while(cin>>C>>D>>len>>N){
		for(int i=0;i<N;i++){
			cin>>Gas[i].price>>Gas[i].distance;
		}
		sort(Gas,Gas+N,cmp);
		if(Gas[0].distance>0){
			cout<<"The maximum travel distance = 0"<<endl;
			continue;
		}
		double least=D,money=0;//least剩余距离 money加油总价钱
		double max=C*len;//加满油能跑的最远距离
		double oil=0;//余油
		//当前路程就是当前加油站离杭州的距离
		for(int i=0;i<N;i++){
			//最后一个加油站了
			if(i==N-1){
				//开不到
				if(max<D-Gas[i].distance){
					printf("The maximum travel distance = %.2f\n",Gas[i].distance+max);
					break;//注意for外
				}else{
					//开得到
					money+=Gas[i].price*((D-Gas[i].distance)/len-oil);
					printf("%.2f\n",money);
					break;
				}
			}
			//加满也开不到下一个加油站
			if(max<Gas[i+1].distance-Gas[i].distance){
				printf("The maximum travel distance = %.2f\n",Gas[i].distance+max);
				break;//注意for外
			}
			//一般情况
			/**
			先找到最近的比当前便宜的站 找不到再遍历找最小的
			*/
			least=D-Gas[i].distance;//当前剩余路程
			int min=i;
			for(int j=i+1;j<N;j++){
				if((Gas[j].distance-Gas[i].distance)<=max && Gas[j].price<Gas[min].price){
					min=j;
					break;
				}
			}
			if(min==i){//当前最便宜 接着找次便宜的
				if(least<=max){//能直接开到了
					money+=Gas[i].price*(least/len-oil);
					printf("%.2f\n",money);
					break;
				}

				min=i+1;
				for(int j=i+2;j<N;j++){
					if((Gas[j].distance-Gas[i].distance)<=max && Gas[j].price<Gas[min].price) min=j;
				}
				
				//自己最小,必须加满,但只开到次小,到时候油有余量  (开不到的前提下)
				money+=Gas[i].price*(max/len-oil);//加满
				oil=max/len-(Gas[min].distance-Gas[i].distance)/len;//剩余油量
				i=min-1;//下次到min  循环体里还有i++	
			}else{
				//当前不是最便宜的 不能多加
				if(oil>=(Gas[min].distance-Gas[i].distance)/len){
					//不用加 余下的油能直接开到
					oil-=(Gas[min].distance-Gas[i].distance)/len;
					i=min-1;//i的变化一定要在最后 因为i时刻要用
				}else{
					//余下的油开不到
					money+=Gas[i].price*((Gas[min].distance-Gas[i].distance)/len-oil);
					oil=0;//加到正好开完
					i=min-1;
				}
			}
		}
	}
	return 0;
}

问题 G: 找零钱

时间限制: 1 Sec  内存限制: 128 MB
提交: 148  解决: 106
[提交][状态][讨论版][命题人:外部导入]

题目描述

小智去超市买东西,买了不超过一百块的东西。收银员想尽量用少的纸币来找钱。
纸币面额分为50 20 10 5 1 五种。请在知道要找多少钱n给小明的情况下,输出纸币数量最少的方案。 1<=n<=99;

输入

有多组数据  1<=n<=99;

输出

对于每种数量不为0的纸币,输出他们的面值*数量,再加起来输出

样例输入

25
32

样例输出

20*1+5*1
20*1+10*1+1*2

代码:

#include<iostream>
using namespace std;
int a[]={50,20,10,5,1};

int main(){
	int n;
	while(cin>>n){
		int b[5]={0};
		bool flag=true;
		for (int i = 0; i < 5&&n>0; ++i)
		{
			if(n>=a[i]){
				b[i]=n/a[i];
				if(b[i]){
					if(flag) {
						cout<<a[i]<<"*"<<b[i];
						flag=false;
					}else{
						cout<<"+"<<a[i]<<"*"<<b[i];
					}
				}
				n=n%a[i];
			}
		}
		cout<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hza419763578/article/details/82952596
今日推荐