贪心相关的习题

问题 A: 看电视 【★★】

http://codeup.cn/problem.php?cid=100000584&pid=0
在这里插入图片描述
在这里插入图片描述
思路: 区间贪心

#include<cstdio>
#include<algorithm>
using namespace std;
struct student
{
    
    
	int left;
	int right;
}stu[105];
bool cmp(student a,student b)
{
    
    
	if(a.left==b.left)
		return a.right<b.right;
	return a.left>b.left; 
}
int main(void)
{
    
    
	int n;
	int i;
	while(1)
	{
    
    
		scanf("%d",&n);
		int number=1;
		if(n==0)
			return 0;
		for(i=0;i<n;i++)
		{
    
    
			scanf("%d %d",&stu[i].left,&stu[i].right);
		}
		sort(stu,stu+n,cmp);
		int leftx=stu[0].left;
		for(i=1;i<n;i++)
		{
    
    
			if(leftx>=stu[i].right)
			{
    
    
				number++;
				leftx=stu[i].left;
			}
		}
		printf("%d\n",number);
	}
} 

问题 B: 出租车费 【★】

http://codeup.cn/problem.php?cid=100000584&pid=1
在这里插入图片描述
在这里插入图片描述
思路:
1~4 每公里 2.5
5~8 每公里 2
大于8 每公里 2.4

#include<cstdio>
int main(void)
{
    
    
	long int number;
	double sum;
	while(1)
	{
    
    
		scanf("%d",&number);
		if(number==0)
			return 0;
		sum=0;
		int flag=0;
		if(number<=4)
			sum=10;
		if(number<=8&&number>4)
      		sum=10+(number-4)*2;				
		if(number<12&&number>8)
		{
    
    
			sum=18+(number-8)*2.4;
			flag=1;//表示结果不是整数
		}	
		if(number>=12)
		{
    
    
			sum=(number/8)*18;
			if((number%8)<=4)
			{
    
    
	        	sum=sum+(number%8)*2.4;
	        	if(number%8==0)
	        		flag=0;
	        	else
	        		flag=1;
			}
			else
			{
    
    
				sum=sum+((number%8)-4)*2+10;
			}
		}
		if(flag)
		printf("%.1lf\n",sum);
		else
		printf("%ld\n",(int)sum);
	}			
	return 0;
}

问题 C:To Fill or Not to Fill 【★★★】

http://codeup.cn/problem.php?cid=100000584&pid=2
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
摘自:https://blog.csdn.net/myRealization/article/details/80154726
思路
输入的是:
油箱的最大容量
到终点的距离
每升油能跑多远,
加油站的总数。

接下来是N行,
单位汽油价格, 这个站到杭州(原点)的距离

输出是:
到达终点的话,输出最少的钱
没有到达终点的话 输出最长的距离
本题我这里一共列举了三种方法。
第一种是别人写的。
第二种是网上找的和我自己写的代码思路差不多
第三种是我写的思路感觉比较清晰,就是代码太冗长了。

代码一:

#include <cstdio>
#include <algorithm>
using namespace std;
typedef struct gasStation {
    
    
	double p, d, s; //p: 价格,d:据出发点距离,s:离上个站点的间距
} gs;
bool cmp(gs a, gs b) {
    
    
	return a.d < b.d; 
}

int main() {
    
    
	double C, D, Davg; 
	int n;  //从杭州到目的地的加油站数目 
	while (scanf("%lf%lf%lf%d", &C, &D, &Davg, &n) != EOF) {
    
    
		gs gstat[n + 1];
		double maxl = C * Davg; //满油后最大行驶距离 
		for (int i = 0; i < n; i++) {
    
    
			scanf("%lf%lf", &gstat[i].p, &gstat[i].d);
		}
		gstat[n].p = 0; //目的地 
		gstat[n].d = D;
		sort(gstat, gstat + n + 1, cmp);
		for (int i = 1; i <= n; i++) {
    
    
			gstat[i].s = gstat[i].d - gstat[i - 1].d;
		}
		int flag = 1;
		/* 如果第一个加油站不在杭州, 没法加油 */
		if (gstat[0].d > 0) {
    
    
			flag = 0;
			printf("The maximum travel distance = 0.00\n");
		} else {
    
    
			for (int i = 1; i <= n; i++) {
    
    
				if (gstat[i].s > maxl) {
    
     //有站点不可达 
					flag = 0;
					printf("The maximum travel distance = %.2f\n", gstat[i - 1].d + maxl);
					break;
				}
			}
		}
		double cost = 0, nowTank = 0;
		int nowSta = 0, signal = 1; 
		if (flag) {
    
     
			for (int i = 0; i < n; i++) {
    
    
				if (i != nowSta) continue;
				for (int j = i + 1; j <= n && (gstat[j].d - gstat[i].d) <= maxl; j++) {
    
    
					if (gstat[j].p < gstat[nowSta].p) {
    
    
		        	   if (nowTank < (gstat[j].d - gstat[nowSta].d) / Davg) {
    
    
		        	       cost += 	gstat[nowSta].p * ((gstat[j].d - gstat[nowSta].d) / Davg - nowTank);
		        	       nowTank = 0;
					   } else nowTank -= (gstat[j].d - gstat[nowSta].d) / Davg;
					   nowSta = j;
					   signal = 1;
					   break;
					} else signal = 0;
				}
		        if (!signal) {
    
    
		        	cost += gstat[i].p * (C - nowTank);
		        	nowTank = C - (gstat[i + 1].s / Davg);
		        	nowSta++;
				}
			} 
			printf("%.2f\n", cost);
		}
	}
	return 0;

代码二:
在这里插入图片描述
本代码的思路就是,找到你可以到达的加油站中最便宜的。
再看找到的加油站的价钱和你当前的加油站的价钱哪个更便宜。
如果找到的加油站便宜的话就去那个加油站
否则就加满油再去那个加油站

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 510;
const int INF = 1000000000;
struct station
{
    
    
	double price, dis;//价格、与起点的距离
}st[maxn];
bool cmp(station a, station b)
{
    
    
	return a.dis < b.dis;//按距离从小到大
}
int main()
{
    
    
	int n;
	double Cmax, D, Davg;
	scanf("%lf%lf%lf%d", &Cmax, &D, &Davg, &n);
	for (int i = 0; i < n; i++)
	{
    
    
		scanf("%lf%lf", &st[i].price, &st[i].dis);
	}
	st[n].price = 0;//数组最后面放置终点,价格为0
	st[n].dis = D;//终点距离为D
	sort(st, st + n, cmp);//将所有加油站按距离从小到大排序
	if (st[0].dis != 0)//如果排序后的第一个加油站距离不是0,说明无法前进
	{
    
    
		printf("The maximum travel distance = 0.00\n");
	}
	else
	{
    
    
		int now = 0;//当前所处的加油站编号
		//总花费、当前油量及满油行驶距离
		double ans = 0, nowTank = 0, MAX = Cmax*Davg;
		while (now < n)//每次循环选出下一个需要加油的站
		{
    
    //选出从当前加油站满油能到达范围内的第一个油价低于当前油价的加油站
			//如果没有低于当前油价的加油站,则选择价格最低的那个
			int k = -1;//最低油价的加油站的编号
			double priceMin = INF;//最低油价
			for (int i = now + 1; i <= n&&st[i].dis - st[now].dis <= MAX; i++)
			{
    
    
				if (st[i].price < priceMin)//如果油价比当前最低油价低
				{
    
    
					priceMin = st[i].price;//更新最低油价
					k = i;
					//如果找到第一个油价低于当前油价的加油站,直接中断循环
					if (priceMin < st[now].price)
					{
    
    
						break;
					}
				}
			}
			if (k == -1)break;//满油状态下无法找到加油站,退出循环输出的结果
			//下面为能找到可到达的加油站k,计算转移花费
			//need为从now到k需要的油量
			double need = (st[k].dis - st[now].dis) / Davg;
			if (priceMin < st[now].price)//如果加油站k的油价低于当前油价
			{
    
    
					ans += (need - nowTank)*st[now].price;//补足need
					nowTank = 0;//到达加油站k后油箱内油量为0		
			}
			else//如果加油站k的油价高于当前油价
			{
    
    
				ans += (Cmax - nowTank)*st[now].price;//将油箱加满
				//到达加油站k后油箱内油量为Cmax-need
				nowTank = Cmax - need;
			}
			now = k;//到达加油站k,进入下一层循环
		}
		if (now == n)//能到达终点
		{
    
    
			printf("%.2f\n", ans);
		}
		else//不能到达终点
		{
    
    
			printf("The maximum travel distance = %.2f\n", st[now].dis + MAX);
		}
	}
	return 0;
}

代码三:
我的思路就是先看可不可以到达。
可以的话就计算可以到达的最小价钱。
思路: 就是从我当前加油站为起点,找到我可以去的比我便宜的加油站 ,去那个加油站。
否则的话说明我现在所处的加油站就是最优的。那么加满油去,可以到达的加油站中价钱最便宜的加油站。

#include<cstdio>
#include<algorithm>
using namespace std;
struct gas
{
    
    
	double price;
	double km;
}g[520];
bool cmp(gas a,gas b)//距离由小到大排 
{
    
    
	return a.km<b.km;
}
int main(void)
{
    
    
	double max_oil;//最大的油量 
	double km;//距离 
	double speed;//速度
	int n;//油箱的数目
	int i;//循环变量 
	double maxkm=0; //满油的最远距离
	bool flag=true; //判断可不可以到达 
	double x=0;//不可到达的,最远距离  
	
	scanf("%lf%lf%lf%d",&max_oil,&km,&speed,&n); 
	maxkm=max_oil*speed;//满油的最远距离 
	for(i=0;i<n;i++)
	{
    
    
		scanf("%lf%lf",&g[i].price,&g[i].km);
	}
	//哨兵 
	g[n].price = 0;//数组最后面放置终点,价格为0
	g[n].km = km;//终点距离为km
	
	sort(g,g+n,cmp);//按距离从小到大排序 
	if(g[0].km!=0)//原点没有加油站 
	{
    
    
		flag=false;
		printf("The maximum travel distance = 0.00\n");
		return 0;
	}
	else//原点有加油站判断可不可以到达 
	{
    
     
		for(i=1;i<n;i++)
		{
    
    
			if(maxkm< (g[i].km-g[i-1].km) )//我的最远距离不能到达下一个加油站。 
			{
    
    
				x=g[i-1].km+maxkm;
				flag=false;
				break;
			}
			x=g[i].km;
		}
		if(i==n)//说明我可以到最后一个加油站。 
		{
    
    
			if(maxkm < ( km-g[n-1].km) )
			{
    
    
				//最后一个加油站到终点的距离大于我的最大行驶距离 
				flag=false;
				x=g[n-1].km+maxkm;
			}
		} 
	}
	if(flag)
	{
    
    
		int now=0;//当前所在的加油站编号 初始为0
		double now_oil=0;//现在的油量
		double money=0;//总的金钱。 
		while(now<n)
		{
    
    
			int minPrice_index=-1;//最便宜的油的编号
			double minPrice=100000;
     		for(i=now+1;i<=n&&(g[i].km-g[now].km)<=maxkm;i++)//找到可以到达的加油站数目 
     		{
    
    
     			if(g[i].price<minPrice)//下一个站的油比我标记的最低油价的低 
     			{
    
    
     				minPrice=g[i].price;//保存 
     				minPrice_index=i;
     				if(minPrice<g[now].price)//如果找到第一个比当前便宜的站 
     					break;
     			}
     		}
     		double need=(g[minPrice_index].km-g[now].km)/speed;
     		if (minPrice < g[now].price)//如果最低加油站的油价,低于当前油价
			{
    
    
					money += (need - now_oil)*g[now].price;//补足need
					now_oil = 0;//到达加油站minPrice_index后油箱内油量为0		
			}
			else//如果加油站minPrice_index的油价高于当前油价
			{
    
    
				money += (max_oil - now_oil)*g[now].price;//将油箱加满
				//到达加油站k后油箱内油量为Cmax-need
				now_oil = max_oil - need;
			}
			now = minPrice_index;//到达加油站minPrice_index,进入下一层循环
		}
		printf("%.2lf\n",money);
	}
	else
	printf("The maximum travel distance = %.2lf\n",x);
	return 0;
} 

问题 D:修复墙壁

http://codeup.cn/problem.php?cid=100000584&pid=3

http://codeup.cn/problem.php?cid=100000584&pid=3
在这里插入图片描述
思路: 排序后。按照大小依次拿直到满足条件或拿完。

#include<cstdio>
#include<algorithm>
using namespace std;
int a[605];
int main(void)
{
    
    
	long int L,N;
	int i;
	while( scanf("%ld %ld",&L,&N) != EOF )
	{
    
    
		int count=0;
		long int sum=0;
		for(i=0;i<N;i++)
		{
    
    
			scanf("%d",&a[i]);
		}
		sort(a,a+N);
		for(i=N-1;i>=0;i--)
		{
    
    
			sum=sum+a[i];
			count++;
			if(sum>=L)
				break;
		}
		if(sum>=L)
		printf("%d\n",count);
		else
		printf("impossible\n");
	}
	return 0;
}

问题 E:胖子的贸易 【★】

http://codeup.cn/problem.php?cid=100000584&pid=4
在这里插入图片描述

在这里插入图片描述
思路: 按性价比排序。然后挨个换。

#include<cstdio>
#include<algorithm>
using namespace std;
struct student
{
    
    
	int cat;
	int java;
	double score;
}stu[1005];
bool cmp(student a,student b)
{
    
    
	return a.score<b.score;
}
int main(void)
{
    
    
	int M,n;
	int i;
	double sum=0;
	while(1)
	{
    
    
		scanf("%d %d",&M,&n);
		if(M==-1)
			return 0;
		sum=0;
		for(i=0;i<n;i++)
		{
    
    
			scanf("%d %d",&stu[i].cat,&stu[i].java);
			stu[i].score=stu[i].cat/(double)stu[i].java;
		}
		sort(stu,stu+n,cmp);
		for(i=n-1;i>=0;i--)
		{
    
    
			if(M<=stu[i].java)
			{
    
    
				break;
			}
			else
			{
    
    
				sum=sum+stu[i].cat;
				M=M-stu[i].java;
			}
		}
		printf("%.3lf\n",sum+M*stu[i].score);
	}
}

问题 F: 迷瘴【★】

http://codeup.cn/problem.php?cid=100000584&pid=5
在这里插入图片描述
在这里插入图片描述
思路:
溶质 / 体积 = 浓度
溶质 = 体积 * 浓度
浓度越小,说明需要的体积越大。
故先按浓度从小到大排序。
再依次选择

#include<cstdio>
#include<algorithm>
using namespace std;
int main(void)
{
    
    
	int c;
	int n,v,w;
	int i,j;
	double m;//浓度 
	double m1;
	int T;//体积 
	while(scanf("%d",&c) != EOF)
	{
    
    
		for(i=0;i<c;i++)
		{
    
    
			int  a[105]={
    
    0};
			m=0.0;
			T=0;
			scanf("%d%d%d",&n,&v,&w);
			for(j=0;j<n;j++)
			{
    
    
				scanf("%d",&a[j]);
			}	
			sort(a,a+n);
			for(j=0;j<n;j++)
			{
    
    
				m1=(m*T+a[j]*v) / (T+v);
				if(m1<=w)
				{
    
    
					T=v+T;
					m=m1;
				}	
				else
					break;
			}
			if (!T) printf("0 0.00\n");
			else printf("%d %.2lf\n", T, m / 100);  
		}
	}
	return 0;
}

问题 G: 找零钱 【★★】思维很好的题

http://codeup.cn/problem.php?cid=100000584&pid=6
在这里插入图片描述
在这里插入图片描述

#include<cstdio>
int money[5]={
    
    50,20,10,5,1};
int main(void)
{
    
    
	int n;
	int i;
	int m;
	int sum;
	while( scanf("%d",&n) != EOF )
	{
    
    
		int  hush[51]={
    
    0};
		for(i=0;i<5;i++)
		{
    
    
			hush[ money[i] ]=n/money[i];
			n=n%money[i];
			if( hush[ money[i] ] !=0  )
			{
    
    
				if(n!=0)//看是不是要结束了
				printf("%d*%d+",money[i],hush[money[i]]);
				else//是最后的,就不需要+号了
				printf("%d*%d\n",money[i],hush[money[i]]);
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_46527915/article/details/114826551