课后作业第四章

文章介绍了如何使用贪心策略解决三个问题:1)虚拟汽车在有限加油次数下规划最少加油站;2)实线上的点用固定长度区间覆盖最少区间数;3)数列操作中最大化或最小化极差。每个问题都展示了如何通过贪心方法找出最优解。
摘要由CSDN通过智能技术生成

4-1:一辆虚拟汽车在加满油之后可以行驶 n km。旅途中有 k 个加油站。设计一个有效算法,使得沿途加油的次数最少。终端输入正整数 n 和 k,表示汽车加满油后可行驶 n km,且旅途中有 k 个加油站。接下来输入 k+1个整数,表示第 k 个加油站与第 k-1个加油站之间的距离。第 0 个加油站表示出发地,汽车已加满油。第 k+1个加油站表示目的地。

解:
对于该问题的求解可以用到贪心的思想。

假设这k+1个距离为x1,x2,x3    xk+1

(假设任意两个加油站之间的距离都小于n)

解题思想如下:
i=0;

Kk=0;//表示已经行驶里程,每次加油清零

ans=0;//记录加油次数

Rep (如果i小于等于k+1)

i++

Kk+=xi

如果kk>n;

Ans++

Kk=xi

即从开始行驶,当到达某个加油站时判断能否到达下一个加油站,如果不能到达则在当前加油站加油,否则继续行驶。

代码如下:

#include<iostream>
using namespace std;
int main()
{
	int n, k;
	cin >> n >> k;
	int kk = 0, ans = 0;
	for (int i = 0; i <= k; i++)
	{
		int dis;
		cin >> dis;
		kk += dis;
		if (kk > n)
		{
			ans++;
			kk = dis;
		}
	}
	cout << ans << endl;
}

4-2:设x1,x2,…,xn是实直线上的n 个点。用固定长度的闭区间覆盖这n 个点,至少需要多少个这样的固定长度闭区间?对于给定的实直线上的n个点和闭区间的长度k,设计解此问题的有效算法,计算覆盖点集的最少区间数。

解:

对于该问题的求解可以运用贪心的思想

假设x1,x2,…,xn是按照从小到大排好序后的数列

解题思想如下:

i=0;

ans=0;//记录区间数

l=x1//用来记录区间最左侧点的坐标

Rep (如果i小于等于n)

i++

r=xi;

如果r-l>k;

Ans++

l=r

即每遍历到一个点时,判断该点能否与前面的点被覆盖在一个区间里,如果不能则将该点作为下一个区间的第一个点

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
int a[100007];
int main()
{
	int n, k;
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	sort(a + 1, a + 1 + n);
	int l = a[1],ans=0,r=0;
	for (int i = 1; i <= n; i++)
	{
		r = a[i];
		if (r - l > k)
		{
			ans++;
			l = r;
		}
	}
	if (r - l < k)ans++;
	cout << ans << endl;}

4-3:【数列极差】问题描述:在黑板上写了N个正整数作成的一个数列,进行如下操作:每一次擦去其中的两个数a和b,然后在数列中加入一个数a*b+1,如此下去直至黑板上剩下一个数,在所有按这种操作方式最后得到的数中,最大的max,最小的为min,则该数列的极差定义为M=max-min。

解:
对于该问题的求解仍旧可运用贪心的方法

该题虽然与哈夫曼编码类似,但是完全可以从较简单的贪心思想入手

关键在于弄清楚较大的数的应该先擦去还是后擦去;

假设有5个数

Result=((((x1x2+1)*x3)+1)*x4+1)*x5+1

      =x1x2x3x4x5+x3x4x5+x4x5+x5+1

可见若要求max,大的数应该最后擦去

若要求min,大的数应该首先擦去

根据数学归纳法可知

当有N个数时:

Result=x1x2…xn+x3x4…xn+x4x5…xn+……+xn+1;

递增排序时 result=max

递减排序时 result=min

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
int a[100007];
int n;
bool cmp(int c,int b)
{
	return c >= b;
}
int compute()
{
	int ans = 1;
	int ss = 1;
	for (int i = n; i >= 3; i--)
	{
		ss *= a[i];
		ans += ss;
	}
	ans += ss * a[1] * a[2];
	return ans;
}
int main()
{
	
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	sort(a + 1, a + 1 + n);//正序排序
	int max = compute();
	sort(a + 1, a + 1 + n, cmp);//倒序排序
	int min = compute();
	cout << max - min << endl;
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值