算法设计与分析--贪心算法进阶练习

目录

第1关:虚拟汽车加油问题

第2关:删数问题

第3关:坚果保龄球


 

第1关:虚拟汽车加油问题

任务描述

本关任务:一辆虚拟汽车加满油后可行驶 n km。旅途中有若干加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少,计算最少加油次数。

测试说明

输入格式

终端输入正整数 n 和 k,表示汽车加满油后可行驶 n km,且旅途中有 k 个加油站。

接下来输入 k+1个整数,表示第 k 个加油站与第 k-1个加油站之间的距离。第 0 个加油站表示出发地,汽车已加满油。第 k+1个加油站表示目的地。

输出格式

将计算的最少加油次数输出。如果无法到达目的地,则输出 No Solution 。 平台会对你编写的代码进行测试:

测试输入:

7 7

1 2 3 4 5 1 6 6

预期输出: 4

提示:

本题使用贪心算法来做。其贪心选择为只要能赶到下一个加油站,那咱就不加油.

思路:

其贪心选择为只要能赶到下一个加油站,就不加油.

每次将目前油可以走的距离和两个加油站之间的距离比较,若可以走到下一个加油站,就更新油箱的油量能走到的距离;如果不能走到,就加油,更新油箱油量为满油能走的距离,并回到上一个加油站。

#include<iostream>
using namespace std;
void PetrolS()
{
	int n,k;
	int* dis=new int[k+2];
	cin>>n>>k;
	for(int i=0;i<k+1;i++)
	{
		cin>>dis[i];
	} 
	int i=0,jiayou=0,shengyu=n;
	for(i=0;i<=k;i++)
	{
		if(dis[i]<=shengyu)
		{
			shengyu=shengyu-dis[i];
		}
		else
		{
			jiayou++;
			i--;//回到上一个加油站
			shengyu=n;//加满油能走的距离
		}
	} 
	cout<<jiayou<<endl;
	 
	
}
int main()
{
	PetrolS();
    return 0;
}

 

第2关:删数问题

任务描述

本关任务:键盘输入一个高精度的正整数 N(不超过 250 位),去掉其中任意 k 个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的 Nk,寻找一种方案使得剩下的数字组成的新数最小。

测试说明

输入格式

第一行输入一个高精度的正整数 n。 第二行输入一个正整数k,表示需要删除的数字个数。

输出格式

输出一个整数,最后剩下的最小数。

测试实例

测试输入: 175438 4 预期输出: 13 提示: 我们希望从左开始在尽量大的范围内找到一个最小的数作为结果的第一位,但范围不能超过m+1,否则可能把左边全部m个数删了也无法把找到的数作为第一位,第一位找到后是第二位,同理。

思路:

用字符串来存高精度数,以要删除的数s为循环判定条件,从左往右找大数,找到后删除。并要注意输出时最高位不能为0。

#include<cstdio>
#include<cstring>
char n[250]; 
int s, i, len, flag = 1;
int main()
{
	scanf("%s %d", n, &s);
	len = strlen(n); //这里是长度函数,取n的长度并赋值给len
	while (s != 0)/
	{
		i = 0;
		while (n[i] <= n[i + 1]) //括号内的条件保证了不降序的条件,当它退出时,就是升序数列的末尾了
			i++;
		while (i < len - 1) //这时已经找到了要取出的数——n[i],这是取出的过程
		{
			n[i] = n[i + 1]; i++;
		}
		len--;
		s--; 
	}
	for (int i = 0; i < len; i++)
	{
		if (n[i] == '0' && i < len - 1 && flag == 1)
			continue;
		else
		{
			printf("%c", n[i]); flag = 0;
		}//输出并且明确n[i]不再是最高位
	}
	return 0;
}

第3关:坚果保龄球

任务描述

PVZ这款游戏中,有一种坚果保龄球。zombie从地图右侧不断出现,向左走,玩家需要从左侧滚动坚果来碾死他们。

我们可以认为地图是一个行数为6,列数为60的棋盘。zombie出现的那一秒站在这一行的第60列,之后每秒向左移动一步。玩家可以随时在屏幕最某一行第一列摆放坚果,这一行的zombie瞬间全被滚过去的坚果碾死。如果zombie走到第1列没有被消灭,如果再向左走,则你的大脑就会被zombie吃掉。

现在有n只zombie!告诉你每只zombie出现的时间以及在出现的行数(可能会同时出现同一位置的僵尸),请问至少需要多少坚果才能消灭所有的zombie。

测试说明

输入格式

第一行一个正整数n,表示zombie数量。 之后n行中,每行两个正整数P和t,分别表示zombie所在行和zombie出现的时间。

输出格式

一个正整数,最少需要的坚果数。

测试输入:

  1. 10
  2. 1 1
  3. 1 61
  4. 2 1
  5. 2 60
  6. 3 1
  7. 3 2
  8. 3 3
  9. 3 4
  10. 4 1
  11. 4 99999

预期输出: 6

提示:

  • 数据规模 n<=2000,t<=100000,1<=P<=6
  • 各行互不干扰,坚果数是各行坚果数总和
  • 当第一波僵尸中走最远的到达第60列时放坚果,然后等待下一波的僵尸,如此往复即可得到最优解
#include<iostream>
using namespace std;
void Zombie()
{
	int zombie[7][2010];//存僵尸来到的时间--如果僵尸死了,就把时间设置为0
	int num[7] = { 0 };//存每行的僵尸数
	int p, t,n,sum=0;
	cin >> n;//僵尸个数
	for (int i = 0; i < n; i++)
	{
		cin >> p >> t;
		num[p]++;
		zombie[p][num[p]] = t;
	}
	int i, j;
	for (i = 1; i < 7; i++)
	{
		for (j = 1; j <=num[i];j++)
		{
			int time = zombie[i][j];
			sum++;
			while (time + 60 > zombie[i][j+1] && j < num[i])//判断接下来的60秒内这一行是否还有僵尸出现
			{
				j++;/
			}
		}
	}
	cout << sum << endl;//放坚果保龄球
}

int main()
{
	Zombie();
    return 0;
}

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值