算法基础知识——贪心策略

目录:

  1. 基础知识

    1. 贪心策略(自顶向下设计、局部最优、无后效性、最优子结构)
    2. 活动选择问题
    3. 动态规划算法和贪心算法区别
  2. 应用实例
    1. 鸡兔同笼【北京大学】
    2. FatMouse' Trade【王道机试】
    3. Senior's Gun【王道机试】
    4. 代理服务器【清华大学】
    5. 今年暑假不AC【王道机试】
    6. Case of Fugitive【Codeforces】
    7. To Fill or Not to Fill【浙江大学】

一、基础知识

1、贪心策略:

  • 定义:总是做出局部最优的选择。对于特定的最优化问题,贪心策略保证一定能够收敛到全局最优解。
  • 贪心算法自顶向下的设计:做出一个选择,然后求解剩下的那个子问题,而不是自底向上地求解出很多子问题,然后再做出选择。
  • 术语定义:
    • 无后效性:某个状态以前的过程不会影响以后的状态,而只与当前状态有关。
    • 最优子结构:如果一个问题的最优解包含其子问题的最优解,则称此问题具有最优子结构性质。
  • 核心思想:总是选择当前状态下最优的策略。并不以整体最优进行考虑,而只考虑当前这一步,可获得局部最优解。
  • 应用场景:
    • 在遇到求最大、最小、最多等多值问题时,应优先考虑用贪心策略求解。
    • 若问题满足最优子结构性质,即该问题无后效性,那么全局的最优解便可由求子问题的最优解得到。
  • 常见题型:
    • 简单贪心
    • 区间贪心:当有多个不同的区间存在,且这些区间有可能相互重叠的时候,如何选择才能从众多区间中,选取最多的两两互不相交的区间。
  • 贪心算法设计过程:
    • 确定问题的最优子结构
    • 设计一个递归算法
    • 证明如果我们做出一个贪心选择,只剩下一个子问题
    • 证明做出贪心选择后,原问题总是存在最优解,即贪心选择总是安全的
    • 设计一个递归算法实现贪心策略
    • 将递归算法转换为迭代算法

2、活动选择问题:

  • 问题描述:一个调度竞争共享资源的多个活动的问题,目标是选出一个最大的互相兼容的活动集合。

    • 兼容定义:每个活动Ai都有一个开始时间Si和结束时间Fi,如果被选中,任务Ai发生在[ Si, Fi )期间。如果两个活动Ai和Aj满足[ Si, Fi )和[ Sj, Fj )不重叠,则称它们是兼容的。
  • 在动态规划策略中,有:
    • c[i, j] = 0,若Sij = ∅
    • c[i, j] = max{ c[i, k] + c[k, j] + 1},若Sij ≠ ∅
  • 在贪心策略中:
    • 思路:

      • 首先应该选择这样一个活动,选出它后剩下的资源应能被尽量多的其他任务所用。因此可以选择最早结束的活动,记为A1。
      • 然后选择在A1结束后开始的活动。

3、动态规划算法和贪心算法区别:

  • 动态规划算法先求解子问题才能进行第一次选择;贪心算法在进行第一次选择之前不求解任何子问题。
  • 动态规划算法是自底向上进行计算的(如果自顶向下求解,需要建立备忘机制);贪心算法通常是自顶向下的,进行一次又一次选择,将给定问题实例变得更小。
  • 动态规划算法的选择通常依赖于子问题的解,贪心算法的选择可能依赖于之前做出的选择,但不依赖于任何将来的选择或者子问题的解。

二、应用实例

1、题目描述:一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物。【北京大学】

  • 输入格式:每组测试数据占1行,每行一个正整数a (a < 32768)
  • 输出格式:输出包含n行,每行对应一个输入,包含两个正整数,第一个是最少的动物数,第二个是最多的动物数,两个正整数用一个空格分开。如果没有满足要求的答案,则输出两个0。
  • 样例输入:
    • 2
    • 3
    • 20
  • 样例输出:
    • 0 0
    • 5 10

示例代码1:

#include <iostream>using namespace std;const int RABBIT_FOOT = 4;
const int CHICKEN_FOOT = 2;int main(){int foot;while(cin >> foot){int tmp1 = foot, tmp2 = foot;int most = 0, less = 0;while(tmp1 >= CHICKEN_FOOT){most++;tmp1 -= CHICKEN_FOOT;}while(tmp2 >= RABBIT_FOOT){less++;tmp2 -= RABBIT_FOOT;}while(tmp2 >= CHICKEN_FOOT){less++;tmp2 -= CHICKEN_FOOT;}if(tmp1 == 0 && tmp2 == 0){cout << less << " " << most << endl;}else{cout << "0 0" << endl;}}return 0;
}

示例代码2:

#include <iostream>using namespace std;int main(){int foot;while(cin >> foot){int most = 0, less = 0;if(foot % 2 == 0){most = foot / 2;less = foot / 4 + (foot % 4) / 2;}cout << less << " " << most << endl;}return 0;
}

2、题目描述:FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean. The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and requires F[i] pounds of cat food. FatMouse does not have to trade for all the JavaBeans in the room, instead, he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food. Here a is a real number. Now he is assigning this homework to you: tell him the maximum amount of JavaBeans he can obtain. 【王道机试】

  • 输入格式:The input consists of multiple test cases. Each test case begins with a line containing two non-negative integers M and N. Then N lines follow, each contains two non-negative integers J[i] and F[i] respectively. The last test case is followed by two -1's. All integers are not greater than 1000.
  • 输出格式:For each test case, print in a single line a real number accurate up to 3 decimal places, which is the maximum amount of JavaBeans that FatMouse can obtain.
  • 样例输入:
    • 5 3
    • 7 2
    • 4 3
    • 5 2
    • 20 3
    • 25 18
    • 24 15
    • 15 10
    • -1 -1
  • 样例输出:
    • 13.333
    • 31.500

示例代码:

#include <iostream>
#include <queue>
#include <iomanip>using namespace std;struct Mouse{double javabean;double catF;Mouse(double j, double c):javabean(j), catF(c){};
};bool operator<(const Mouse &m1, const Mouse &m2){if(m1.catF == 0 && m2.catF == 0){return m1.javabean < m2.javabean;}if(m1.catF == 0){return false;}if(m2.catF == 0){return true;}return m1.javabean / m1.catF < m2.javabean / m2.catF;
}priority_queue<Mouse> myQueue;int main(){double M, N;while(cin >> M >> N && M != -1 && N != -1){double f, j;for(int i = 0; i < N; i++){cin >> j >> f;Mouse mouse(j, f);myQueue.push(mouse);}double answer = 0;while(M >= 0 && myQueue.size() > 0){if(M - myQueue.top().catF >= 0){M -= myQueue.top().catF;answer += myQueue.top().javabean;myQueue.pop();}else{answer += M * (myQueue.top().javabean / myQueue.top().catF);break;}}cout << fixed << setprecision(3) << answer << endl;if(!myQueue.empty()){myQueue.pop();}}return 0;
}

3、题目描述:Xuejiejie is a beautiful and charming sharpshooter.She often carries n guns, and every gun has an attack power a[i].One day, Xuejiejie goes outside and comes across m monsters, and every monster has a defensive power b[j].Xuejiejie can use the gun i to kill the monster j, which satisfies b[j] ≤ a[i], and then she will get a[i]-b[j] bonus.Remember that every gun can be used to kill at most one monster, and obviously every monster can be killed at most once.Xuejiejie wants to gain most of the bonus. It's no need for her to kill all monsters.【王道机试】

  • 输入格式:In the first line there is an integer T, indicates the number of test cases.In each case:The first line contains two integers n,m.The second line contains n integers, which means every gun's attack power.The third line contains m integers, which mean every monster's defensive power.1 ≤ n,m ≤ 100000, -10^9 ≤ a[i],b[j] ≤ 10^9.
  • 输出格式:For each test case, output one integer which means the maximum of the bonus Xuejiejie could gain.
  • 样例输入:
    • 1
    • 2 2
    • 2 3
    • 2 2
  • 样例输出:
    • 1

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;vector<int> monster;
vector<int> gun;int main(){int number;while(cin >> number){int n, m, monsterPower, gunPower;for(int i = 0; i < number; i++){cin >> n >> m;for(int j = 0; j < n; j++){cin >> gunPower;gun.push_back(gunPower);}for(int j = 0; j < m; j++){cin >> monsterPower;monster.push_back(monsterPower);}sort(gun.begin(), gun.end());sort(monster.begin(), monster.end());int bonus = 0, loc = 0;bool flag = false;//强枪杀弱怪for(int j = gun.size() - 1; j >= 0; j--){if(loc == monster.size() || flag){  //杀到最后一只怪了break;}if(monster[loc] <= gun[j]){bonus += gun[j] - monster[loc];loc++;}else{  //你打不过任何一只怪了flag = true;}}cout << bonus << endl;monster.clear();gun.clear();}}return 0;
}

4、题目描述:使用代理服务器能够在一定程度上隐藏客户端信息,从而保护用户在互联网上的隐私。我们知道n个代理服务器的IP地址,现在要用它们去访问m个服务器。这 m 个服务器的 IP 地址和访问顺序也已经给出。系统在同一时刻只能使用一个代理服务器,并要求不能用代理服务器去访问和它 IP地址相同的服务器(不然客户端信息很有可能就会被泄露)。在这样的条件下,找到一种使用代理服务器的方案,使得代理服务器切换的次数尽可能得少。【清华大学】

  • 输入格式:每个测试数据包括 n + m + 2 行。第 1 行只包含一个整数 n,表示代理服务器的个数。第 2行至第n + 1行每行是一个字符串,表示代理服务器的 IP地址。这n个 IP地址两两不相同。第 n + 2 行只包含一个整数 m,表示要访问的服务器的个数。第 n + 3 行至第 n + m + 2 行每行是一个字符串,表示要访问的服务器的 IP 地址,按照访问的顺序给出。每个字符串都是合法的IP地址,形式为“xxx.yyy.zzz.www”,其中任何一部分均是0–255之间的整数。输入数据的任何一行都不包含空格字符。其中,1<=n<=1000,1<=m<=5000。
  • 输出格式:可能有多组测试数据,对于每组输入数据, 输出数据只有一行,包含一个整数s,表示按照要求访问服务器的过程中切换代理服务器的最少次数。第一次使用的代理服务器不计入切换次数中。若没有符合要求的安排方式,则输出-1。
  • 样例输入:
    • 3
    • 166.111.4.100
    • 162.105.131.113
    • 202.112.128.69
    • 6
    • 72.14.235.104
    • 166.111.4.100
    • 207.46.19.190
    • 202.112.128.69
    • 162.105.131.113
    • 118.214.226.52
  • 样例输出:
    • 1

示例代码:

#include <iostream>
#include <string>
#include <vector>using namespace std;vector<string> serverAddress;
vector<string> agentAddress;int main(){int n, serverCount;while(cin >> n){string ip;for(int i = 0; i < n; i++){cin >> ip;agentAddress.push_back(ip);}cin >> serverCount;for(int i = 0; i < serverCount; i++){cin >> ip;serverAddress.push_back(ip);}int answer = 0;bool flag = false;for(int i = 0; i < serverAddress.size(); ){int maxCount = 0;for(int j = 0; j < agentAddress.size(); j++){int count = 0, tmp = i;while(tmp < serverAddress.size() && serverAddress[tmp] != agentAddress[j]){count++;tmp++;}if(count > maxCount){maxCount = count;}}if(maxCount == 0){flag = true;break;}i += maxCount;answer++;}if(flag){cout << -1 << endl;}else{cout << answer - 1 << endl;}serverAddress.clear();agentAddress.clear();}return 0;
}

5、题目描述:“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,如《新闻联播》(永远不要忘记关心国家大事)、《非常6+7》、《超级女生》,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)【王道机试】

  • 输入格式:输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (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 <vector>
#include <algorithm>using namespace std;struct TV{int startTime;int endTime;TV(int s, int e):startTime(s), endTime(e){};
};vector<TV> tvList;bool CompareAsc(const TV &t1, const TV &t2){if(t1.endTime == t2.endTime){return t1.startTime > t2.startTime;}else{return t1.endTime < t2.endTime;}
}int main(){int n;while(cin >> n && n != 0){int st, et;for(int i = 0; i < n; i++){cin >> st >> et;TV tv(st, et);tvList.push_back(tv);}sort(tvList.begin(), tvList.end(), CompareAsc);int answer = 0, currentTime = 0;for(int i = 0; i < tvList.size(); i++){if(currentTime <= tvList[i].startTime){answer++;currentTime = tvList[i].endTime;}}cout << answer << endl;tvList.clear();}return 0;
}

6、题目描述:Andrewid the Android is a galaxy-famous detective. He is now chasing a criminal hiding on the planet Oxa-5, the planet almost fully covered with water.
The only dry land there is an archipelago of n narrow islands located in a row. For more comfort let's represent them as non-intersecting segments on a straight line: island i has coordinates [l i , r i ], besides, r i  < l i + 1 for 1 ≤ i ≤ n - 1.
To reach the goal, Andrewid needs to place a bridge between each pair of adjacent islands. A bridge of length a can be placed between the i -th and the (i + 1)-th islads, if there are such coordinates of x and y , that l i  ≤ x ≤ r i , l i + 1 ≤ y ≤ r i + 1 and y - x = a .
The detective was supplied with m bridges, each bridge can be used at most once. Help him determine whether the bridges he got are enough to connect each pair of adjacent islands.【Codeforces】

  • 输入格式:The first line contains integers n (2 ≤ n ≤ 2*10^5) and m (1 ≤ m ≤ 2*10^5) — the number of islands and bridges.
    Next n lines each contain two integers li and ri (1 ≤ li ≤ ri ≤ 10^18) — the coordinates of the island endpoints.
    The last line contains minteger numbers a1, a2, ..., am (1 ≤ ai ≤ 10^18) — the lengths of the bridges that Andrewid got.
  • 输出格式:If it is impossible to place a bridge between each pair of adjacent islands in the required manner, print on a single line "No" (without the quotes), otherwise print in the first line "Yes" (without the quotes), and in the second line print n - 1 numbers b1, b2, ..., bn - 1, which mean that between islands i and i + 1 there must be used a bridge number bi. 
    If there are multiple correct answers, print any of them. Note that in this problem it is necessary to print "Yes" and "No" in correct case.
  • 备注:In the first sample test you can, for example, place the second bridge between points 3 and 8, place the third bridge between points 7 and 10 and place the first bridge between points 10 and 14.In the second sample test the first bridge is too short and the second bridge is too long, so the solution doesn't exist.
  • 样例输入:
    • 4 4
    • 1 4
    • 7 8
    • 9 10
    • 12 14
    • 4 5 3 8
    • 2 2
    • 11 14
    • 17 18
    • 2 9
    • 2 1
    • 1 1
    • 1000000000000000000 1000000000000000000
    • 999999999999999999
  • 样例输出:
    • Yes
    • 2 3 1
    • No
    • Yes
    • 1

示例代码:

#include <iostream>
#include <algorithm>
#include <vector>using namespace std;struct Island{long long bLeft;long long bRight;int index;Island(long long bl, long long br, int i):bLeft(bl), bRight(br),index(i){};
};struct TwoIslandDistance{long long minLength;long long maxLength;int index;TwoIslandDistance(long long min, long long max, int i):minLength(min), maxLength(max), index(i){};
};struct Bridge{int index;long long bridgeLength;Bridge(int i, long long b):index(i), bridgeLength(b){};
};struct Answer{int bridgeIndex;int islandIndex;Answer(int b, int i):bridgeIndex(b), islandIndex(i){};
};vector<Island> islandList;
vector<TwoIslandDistance> distanceList;
vector<Bridge> bridgeList;
vector<Answer> answerList;bool IslCompareAsc(const Island &i1, const Island &i2){return i1.bLeft < i2.bLeft;
}bool DisCompareAsc(const TwoIslandDistance &t1, const TwoIslandDistance &t2){if(t1.minLength == t2.minLength){return t1.maxLength < t2.maxLength;}else{return t1.minLength < t2.minLength;}
}bool BriCompareAsc(const Bridge &b1, const Bridge &b2){return b1.bridgeLength < b2.bridgeLength;
}bool AnswerCompareAsc(const Answer &a1, const Answer &a2){return a1.islandIndex < a2.islandIndex;
}int main(){int bridgeNumber, islandNumber;long long bLength, iLeft ,iRight;while(cin >> islandNumber >> bridgeNumber){for(int i = 0; i < islandNumber; i++){cin >> iLeft >> iRight;Island island(iLeft, iRight, i);islandList.push_back(island);}sort(islandList.begin(), islandList.end(), IslCompareAsc);long long min, max;for(int i = 0; i < islandList.size() - 1; i++){min = islandList[i + 1].bLeft - islandList[i].bRight;max = islandList[i + 1].bRight - islandList[i].bLeft;TwoIslandDistance distance(min, max, i);distanceList.push_back(distance);}sort(distanceList.begin(), distanceList.end(), DisCompareAsc);for(int i = 1; i <= bridgeNumber; i++){cin >> bLength;Bridge bridge(i, bLength);bridgeList.push_back(bridge);}sort(bridgeList.begin(), bridgeList.end(), BriCompareAsc);bool flag = false;int loc = 0;for(int i = 0; i < bridgeList.size(); i++){if(bridgeList[i].bridgeLength <= distanceList[loc].maxLength && bridgeList[i].bridgeLength >= distanceList[loc].minLength){Answer answer(bridgeList[i].index, distanceList[loc].index);answerList.push_back(answer);loc++;}if(loc == distanceList.size()){flag = true;break;}}if(flag){cout << "Yes" << endl;sort(answerList.begin(), answerList.end(), AnswerCompareAsc);for(int i = 0; i < answerList.size(); i++){cout << answerList[i].bridgeIndex << " ";}cout << endl;}else{cout << "No" << endl;}bridgeList.clear();distanceList.clear();answerList.clear();islandList.clear();}return 0;
}

7、题目描述: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.【浙江大学】

  • 输入格式: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.
  • 样例输入:
    • 50 1300 12 8
    • 6.00 1250
    • 7.00 600
    • 7.00 150
    • 7.10 0
    • 7.20 200
    • 7.50 400
    • 7.30 1000
    • 6.85 300
    • 50 1300 12 2
    • 7.10 0
    • 7.00 600
  • 样例输出:
    • 749.17
    • The maximum travel distance = 1200.00

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>using namespace std;struct Station{double gasPrice;double statDist;Station(double g, double d):gasPrice(g), statDist(d){};
};bool CompareAsc(const Station &s1, const Station &s2){if(s1.statDist == s2.statDist){return s1.gasPrice < s2.gasPrice;}else{return s1.statDist < s2.statDist;}
}int main(){vector<Station> statList;double tankSize, distance, distPerOil, station;while(cin >> tankSize >> distance >> distPerOil >> station){double gasPrice, distStation;for(int i = 0; i < station; i++){cin >> gasPrice >> distStation;Station s(gasPrice, distStation);statList.push_back(s);}sort(statList.begin(), statList.end(), CompareAsc);double maxDist = tankSize * distPerOil;double price = 0.0, currDist = 0.0, currTankSize = 0.0;int currStat = 0;double maxArrive = 0.0;bool flag = true; //能到达目的地为Trueif(statList[0].statDist != 0){flag = false;}while(currDist < distance){if(currStat < statList.size() - 1){double dist = statList[currStat + 1].statDist - statList[currStat].statDist;if(dist > maxDist){maxArrive = currDist + maxDist;flag = false;break;}}//如果下一个加油站油比本加油站便宜,加上能到下一个加油站的油就好if(currStat < statList.size() - 1&& statList[currStat + 1].gasPrice <= statList[currStat].gasPrice){double dist = statList[currStat + 1].statDist - statList[currStat].statDist;double remainOil = dist / distPerOil - currTankSize;if(remainOil > 0){ //当前油量不足price += remainOil * statList[currStat].gasPrice;currTankSize = 0.0;}else{ //当前油量充足,能去下一个加油站,不加油currTankSize -= dist / distPerOil;}currDist += dist;currStat++;}else{if(currStat == statList.size() - 1){ //最后一个油站double remainDist = distance - currDist;if(remainDist > maxDist){maxArrive = currDist + maxDist;flag = false;break;}double remainOil = remainDist / distPerOil - currTankSize;if(remainOil > 0){ //当前油箱中的油不足以去目的地price += remainOil * statList[currStat].gasPrice;}currDist = distance;}//找到满箱油路程中比本油站价格低的油站,加上能到这油站的油//如果没找到,判断是否能到目的地,如果能,加到达目的地的油,如果不能,加满箱油else{double available = statList[currStat].statDist + maxDist;int next = currStat + 1, min_stat = currStat;double minPrice = statList[currStat].gasPrice;bool flag1 = true;//没找到价格更低的油站为Truewhile(next != statList.size() && statList[next].statDist <= available){ //找到下一个最便宜的油站if(statList[next].gasPrice < minPrice){minPrice = statList[next].gasPrice;min_stat = next;flag1 = false;break;}next++;}if(flag1){ //没找到价格更低的油站if(distance - currDist > maxDist){ //加满的情况price += (tankSize - currTankSize) * statList[currStat].gasPrice;Station next = statList[currStat + 1];currDist = next.statDist;currTankSize = tankSize - (currDist - statList[currStat].statDist) / distPerOil;}else{double oilSize = currTankSize - (distance - currDist) / distPerOil;if(oilSize < 0){ price += oilSize * (-1) * statList[currStat].gasPrice;}currDist = distance;}currStat++;}else{double dist = statList[min_stat].statDist - statList[currStat].statDist;double remainOil = dist / distPerOil - currTankSize;//当前油箱中的油不足以去该油站if(remainOil > 0){price += remainOil * statList[currStat].gasPrice;currTankSize = 0.0;}else{currTankSize -= dist / distPerOil;}currDist += dist;currStat = min_stat;}}}}if(flag){cout << fixed << setprecision(2) << price << endl;}else{cout << "The maximum travel distance = " << fixed << setprecision(2) << maxArrive << endl;}statList.clear();}return 0;
}

附注:

(1)给出的测试样例中,

50 1300 12 8
7.10 0           7.10 * (150 / 12) = 88.75
7.00 150       7.00 * (300 - 150) /12 = 87.5
7.20 200
6.85 300       6.85 * 50 = 342.5
7.50 400
7.00 600       用掉了(600 - 300) / 12 = 25,剩余50 - 25 = 25,加满:7.00 * 25 = 175
7.30 1000     加多50公里路程的油, 7.30 * 50 / 12 = 30.42
6.00 1250     加多50公里路程的油, 6.00 * 50 / 12 = 25

88.75 + 87.5 + 342.5 + 175 + 30.42 + 25 = 749.17

参考文献:

[1]Thomas.H.Cormen Charles E. Leiseron、Ronald L. Rivest Clifford Srein. 算法导论(第3版). [M]北京:机械工业出版社,2013.01;
[2]杨泽邦、赵霖. 计算机考研——机试指南(第2版). [M]北京:电子工业出版社,2019.11;

算法基础知识——贪心策略相关推荐

  1. 算法基础知识——二叉树

    算法基础知识--二叉树 目录: 基础知识 基本定义 应用实例 重建二叉树[剑指Offer_编程题] 二叉树的镜像[剑指Offer_编程题] 从上往下打印二叉树[剑指Offer_编程题] 二叉搜索树的后 ...

  2. 算法基础知识总结(基础算法)

    算法基础知识总结 Efficient procedures for solving problems on large inputs. 一.基础算法 1.快速排序 1.类别:快速排序是一种 交换排序, ...

  3. 算法基础知识——动态规划

    算法基础知识--动态规划 目录: 基础知识 分治法和动态规划的区别 动态规划算法设计步骤 最优子结构性质定义 动态规划两种等价的实现方法(自顶向下带备忘.自底向上) 子问题图 经典问题 钢条切割 矩阵 ...

  4. 【Java面试高频问题】Java数据结构和算法基础知识汇总

    文章目录 Java数据结构和算法基础知识 一.Java数据结构 1. 线性结构:数组.队列.链表和栈 1.1 数组(Array) 1.2 稀疏数组 1.3 队列(Queue) 1.4 链表(Linke ...

  5. 数据结构与算法笔记:贪心策略之BSTBBST, Hashtable+Dictionary+Map, Priority Queue~Heap, Minium Spanning Tree

    BST & BBST BST(Binary Search Tree) 二叉搜索树,也就是使用二叉树来做查找 BBST(Balanced Binary Search Tree) 平衡二叉搜索树 ...

  6. 算法设计与分析(电子科技大学)(上)算法基础和贪心算法

    算法分析与设计 引论 (1)理解算法和程序的差别 (2)理解判断问题和优化问题这两类计算问题 1.理解指数增长的规模 2.理解渐进表达式 掌握渐进符号Ο.Θ.Ω的含义,能判断一个函数属于哪个渐近增长阶 ...

  7. 算法提高:贪心策略的11个经典题目

    目录 字典序最小 零钱问题 股票问题(最多持有一支,可以买卖无限次) 小船过河 任务调度器 摆动序列 最小区间 跳跃游戏 II 分糖果 通配符匹配 拼接最大数 字典序最小 题目 给定一个由字符串组成的 ...

  8. 算法基础知识总结(搜索与图论)

    三.搜索与图论 1.树与图的深度优先遍历 1.基本思想:利用深度优先搜素 2.树与图的存储与时间复杂度: (1)邻接矩阵:O(∣V∣2)O(|V|^2)O(∣V∣2) (2)邻接表:O(∣V∣+∣E∣ ...

  9. 机器学习算法基础知识

    在我们了解了需要解决的机器学习问题的类型之后,我们可以开始考虑搜集来的数据的类型以及我们可以尝试的机器学习算法.在这个帖子里,我们会介绍一遍最流行的机器学习算法.通过浏览主要的算法来大致了解可以利用的 ...

  10. 算法基础知识科普:8大搜索算法之红黑树(下)

    这是介绍红黑树的最后一部分,令y为要删除结点,n为要删除结点的子结点(子结点最多有1个),w为y的兄弟结点,删除操作的重点是使红黑树删除结点并通过调整后仍满足自身是搜索二叉树和设定的三点规则.删除操作 ...

最新文章

  1. android gridview 间隔线,Android开发之RecyclerView的间隔线处理
  2. Linux 父进程 子进程 回收,回收 fork() 的子进程
  3. 【全球发布】乘云而上的阿里云MVP
  4. 数学 :追求真和美的学问
  5. 怀旧服推荐配置_【怀旧服】狂暴战P4毕业装备推荐
  6. 后缀数组 TYVJ P1860 后缀数组
  7. QT5主界面“关闭窗口”按钮设置弹出提示询问信息
  8. ENSP实验五——三层交换机+二层交换机
  9. FreeSWITCH折腾笔记5——G729转码支持
  10. java-net-php-python-java校园约球网站计算机毕业设计程序
  11. 【笔记本双屏外界显示屏分辨率调高】解决方法
  12. jquery H5 好用的编辑器umeditor
  13. 删除桌面上出现无文件名图标的方法
  14. JVM:7种垃圾收集器
  15. css实现icon动画效果
  16. 机器翻译古文也翻车?读了20次“苟富贵勿相忘”后,谷歌:没钱的人总会被遗忘...
  17. ie 和火狐兼容问题
  18. SQL语句学习(自学记录)
  19. Curl学习日记2 - 在Windows CMD命令行中使用Curl
  20. 《redis设计与实现 》15复制-源码部分

热门文章

  1. 支付宝是怎么炼成的?蚂蚁金融级研发效能实践解析
  2. centos7部署rap2
  3. UIScrollView与地图页面嵌套效果的实现。
  4. css:table-cell的妙用
  5. IOS ipv6测试
  6. ADB Interface驱动安装[Android Studio开发]
  7. 播布客教学视频_C学习笔记_7_100内最大的素数(97)
  8. RainMeter学习3
  9. 中职一年级计算机学情分析,一年级学情分析.doc
  10. 数据库期末考试(考点以及相关概念整理)