一
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;
}