2019年9月PAT - 练习笔记——4.4
以下页码标注的是阅读器中实际页码,而不是书本身自印的页码。
第4章 入门篇(2)——算法初步
4.4 贪心
注意
- 注意输入输出样例不一定能反应题目要求的数据类型!见B1020
目录
- B1023 组个最小数
- B1020 / A1070 月饼
- A1033 To Fill or Not to Fill
- A1037 Magic Coupon
- A1067 Sort with Swap(0, *)
- A1038 Recover the Smallest Number
-
B1023 组个最小数
给定数字 0-9 各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意 0 不能做首位)。例如:给定两个 0,两个 1,三个 5,一个 8,我们得到的最小的数就是 10015558。
现给定数字,请编写程序输出能够组成的最小的数。
输入格式:
输入在一行中给出 10 个非负整数,顺序表示我们拥有数字 0、数字 1、……数字 9 的个数。整数间用一个空格分隔。10 个数字的总个数不超过 50,且至少拥有 1 个非 0 的数字。
输出格式:
在一行中输出能够组成的最小的数。
输入样例:
2 2 0 0 0 3 0 0 1 0
输出样例:
10015558
-
我的
#include <iostream> #include <vector> using namespace std; int main(void) { const int n = 10; vector<int> nums(n); for (int i = 0;i < n;++i) cin >> nums[i]; int i = 1; for (;!nums[i];++i); cout << i; --nums[i]; for (int j = 0;j < n;++j) { for (int k = 0;k < nums[j];++k) cout << j; } return 0; }
-
《算法笔记》P156
-
-
B1020 / A1070 月饼
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有 3 种月饼,其库存量分别为 18、15、10 万吨,总售价分别为 75、72、45 亿元。如果市场的最大需求量只有 20 万吨,那么我们最大收益策略应该是卖出全部 15 万吨第 2 种月饼、以及 5 万吨第 3 种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入格式:
每个输入包含一个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N 表示月饼的种类数、以及不超过 500(以万吨为单位)的正整数 D 表示市场最大需求量。随后一行给出 N 个正数表示每种月饼的库存量(以万吨为单位);最后一行给出 N 个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出格式:
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后 2 位。
输入样例:
3 20 18 15 10 75 72 45
输出样例:
94.50
-
我的
#include <iostream> #include <vector> #include <algorithm> using namespace std; typedef struct { float stock; float price; }Mooncake; bool Cmp(const Mooncake&a, const Mooncake&b) { return a.price > b.price; } int main(void) { int n = 0, d = 0; cin >> n >> d; vector<Mooncake> mooncakes(n); for (int i = 0;i < n;++i) cin >> mooncakes[i].stock; for (int i = 0;i < n;++i) { cin >> mooncakes[i].price; mooncakes[i].price /= mooncakes[i].stock; } sort(mooncakes.begin(), mooncakes.end(), Cmp); float profit = 0; for (int i = 0;d && i < n;++i) { if (d > mooncakes[i].stock) { d -= mooncakes[i].stock; profit += mooncakes[i].stock * mooncakes[i].price; } else { profit += d * mooncakes[i].price; d = 0; } } printf("%.2f", profit); return 0; }
-
《算法笔记》P157
“月饼库存量和总售价可以是浮点数(题目中只说是正数,没说是正整数)……总需求量D虽然题目说是正整数,但是为了后面计算方便,也需要定义为浮点型”
我D定义为整型也过了,但像上面说的那样,应该需要定义为浮点型才对。
-
-
A1033 To Fill or Not to Fill
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.
Input Specification:
Each input file contains one test case. 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.
Output Specification:
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
whereX
is the maximum possible distance the car can run, accurate up to 2 decimal places.Sample Input 1:
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
Sample Output 1:
749.17
Sample Input 2:
50 1300 12 2 7.10 0 7.00 600
Sample Output 2:
The maximum travel distance = 1200.00
-
我的
#include <iostream> #include <vector> #include <algorithm> using namespace std; const double EPS = 1E-9; typedef struct { double pi; double di; }Station; bool Cmp1(const Station&a, const Station&b) { return a.di < b.di; } typedef struct { double pi; double capacity; }Gas; bool Cmp2(const Gas&a, const Gas&b) { return a.pi < b.pi; } int main(void) { double cmax = 0, d = 0, davg = 0, n = 0; cin >> cmax >> d >> davg >> n; vector<Station> stations(n); for (int i = 0;i < n;++i) cin >> stations[i].pi >> stations[i].di; sort(stations.begin(), stations.end(), Cmp1); stations.push_back({0, d}); double tank = 0, dist = 0, price = 0; vector<Gas> gas; if (stations[0].di) cout << "The maximum travel distance = 0.00"; else { gas.push_back({stations[0].pi, cmax}); tank = cmax; for (int i = 1;dist < d && i <= n;++i) { double nowd = stations[i].di - stations[i - 1].di; if (d - dist < nowd) nowd = d - dist; double need = nowd / davg; if (!(tank < need)) { tank -= need; for (;need >= EPS;) { if (need > gas[0].capacity) { need -= gas[0].capacity; price += gas[0].capacity * gas[0].pi; gas.erase(gas.begin()); } else { gas[0].capacity -= need; price += need * gas[0].pi; need = 0; } } } else { printf("The maximum travel distance = %.2lf", dist + tank * davg); break; } dist += nowd; sort(gas.begin(), gas.end(), Cmp2); for(;gas.size() >= 1 && gas[gas.size() - 1].pi > stations[i].pi;) { tank -= gas[gas.size() - 1].capacity; gas.erase(gas.end() - 1); } if (tank < cmax) { gas.push_back({stations[i].pi, cmax - tank}); tank = cmax; } } if (!(dist < d)) printf("%.2lf", price); } return 0; }
这题印象也很深,当初不会做,看完牛客网的题解拍案叫绝:https://www.nowcoder.com/discuss/398
这次虽然不是很顺,几个细节处找了好久bug,但总算能独立做出来了
测试点2:第一个加油站不在起点处
-
《算法笔记》P159
-
-
A1037 Magic Coupon
The magic shop in Mars is offering some magic coupons. Each coupon has an integer N printed on it, meaning that when you use this coupon with a product, you may get N times the value of that product back! What is more, the shop also offers some bonus product for free. However, if you apply a coupon with a positive N to this bonus product, you will have to pay the shop N times the value of the bonus product… but hey, magically, they have some coupons with negative N’s!
For example, given a set of coupons { 1 2 4 −1 }, and a set of product values { 7 6 −2 −3 } (in Mars dollars M$) where a negative value corresponds to a bonus product. You can apply coupon 3 (with N being 4) to product 1 (with value M$7) to get M$28 back; coupon 2 to product 2 to get M$12 back; and coupon 4 to product 4 to get M$3 back. On the other hand, if you apply coupon 3 to product 4, you will have to pay M$12 to the shop.
Each coupon and each product may be selected at most once. Your task is to get as much money back as possible.
Input Specification:
Each input file contains one test case. For each case, the first line contains the number of coupons NC, followed by a line with NC coupon integers. Then the next line contains the number of products NP, followed by a line with NP product values. Here 1≤NC,NP≤105, and it is guaranteed that all the numbers will not exceed 230.
Output Specification:
For each test case, simply print in a line the maximum amount of money you can get back.
Sample Input:
4 1 2 4 -1 4 7 6 -2 -3
Sample Output:
43
-
我的
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main(void) { int nc = 0; cin >> nc; vector<int> coupons(nc); for (int i = 0;i < nc;++i) cin >> coupons[i]; sort(coupons.begin(), coupons.end(), greater<int>()); int np = 0; cin >> np; vector<int> products(np); for (int i = 0;i < np;++i) cin >> products[i]; sort(products.begin(), products.end(), greater<int>()); int profit = 0; int i1 = 0, i2 = 0; for (;i1 < nc && i2 < np && coupons[i1] > 0 && products[i2] > 0;++i1, ++i2) profit += coupons[i1] * products[i2]; while (coupons[i1] >= 0 && i1 < nc) ++i1; while (products[i2] >= 0 && i2 < np) ++i2; for (int j1 = nc - 1, j2 = np - 1;j1 >= i1 && j2 >= i2;--j1, --j2) profit += coupons[j1] * products[j2]; cout << profit; return 0; }
注意x > 0时,x越大|x|越大;x < 0时,x越小|x|越大
-
《算法笔记》P164
-
-
A1067 Sort with Swap(0, *)
Given any permutation of the numbers {0, 1, 2,…, N−1}, it is easy to sort them in increasing order. But what if
Swap(0, *)
is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:Swap(0, 1) => {4, 1, 2, 0, 3} Swap(0, 3) => {4, 1, 2, 3, 0} Swap(0, 4) => {0, 1, 2, 3, 4}
Now you are asked to find the minimum number of swaps need to sort the given permutation of the first N nonnegative integers.
Input Specification:
Each input file contains one test case, which gives a positive N (≤105) followed by a permutation sequence of {0, 1, …, N−1}. All the numbers in a line are separated by a space.
Output Specification:
For each case, simply print in a line the minimum number of swaps need to sort the given permutation.
Sample Input:
10 3 5 7 2 6 4 9 0 8 1
Sample Output:
9
-
我的
#include <iostream> #include <vector> #include <algorithm> using namespace std; bool flag = false; int Find(const int pos, vector<int>& nums) { if (!nums[pos]) flag = true; if (pos != nums[pos]) { int nextPos = nums[pos]; nums[pos] = pos; return Find(nextPos, nums) + 1; } else return 0; } int main(void) { int n = 0; cin >> n; vector<int> nums(n); for (int i = 0;i < n;++i) cin >> nums[i]; int count = 0; for (int i = 0;i < n;++i) { if (i != nums[i]) { flag = false; count += Find(i, nums); flag ? --count : ++count; } } cout << count; return 0; }
印!象!深!刻!当初也是看完牛客网的题解才理解:https://www.nowcoder.com/discuss/432
这次能做出来了,但做的磕磕绊绊的……还是要多练
-
《算法笔记》P167
-
-
A1038 Recover the Smallest Number
Given a collection of number segments, you are supposed to recover the smallest number from them. For example, given { 32, 321, 3214, 0229, 87 }, we can recover many numbers such like 32-321-3214-0229-87 or 0229-32-87-321-3214 with respect to different orders of combinations of these segments, and the smallest number is 0229-321-3214-32-87.
Input Specification:
Each input file contains one test case. Each case gives a positive integer N (≤104) followed by N number segments. Each segment contains a non-negative integer of no more than 8 digits. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the smallest number in one line. Notice that the first digit must not be zero.
Sample Input:
5 32 321 3214 0229 87
Sample Output:
22932132143287
-
我的
想不出好办法,直接看书 看过牛客网的题解,但是不记得是什么了
-
《算法笔记》P170
-
“……对数字串s1与s1,如果s1+s2 < s2+s1(加号表示拼接),那么把s1放在s2的前面;否则,把s2放在s1的前面”
“证明:假设有数字串s1 + s2 + … + sk-1 + sk + … + sn, 且对任意i∈[1,n],有sk + si < si + sk成立(也就是说,sk与其它数字串拼接时,sk总是排在前面更优)。那么考虑sk-1 + sk部分,显然有sk + sk-1 < sk-1 + sk成立,因此s1 + s2 + … + sk + sk-1 + … + sn < s1 + s2 + … + sk-1 + sk + … + sn成立,这样sk就提前了一个位置。接下来考虑sk-2 + sk部分,同理可以得到s1 + s2 + … + sk + sk-2 + … + sn < s1 + s2 + … + sk-2 + sk + … + sn”,因此sk又提前了一个位置。依此类推,最终sk将提前到第一个位置,得到sk + s1 + s2 + … + sk-1 + sk+1 + … + sn。同理,对sk之后的部分也可以使用童颜的思路将某个数字串提前到sk的后面,使得结果串变更小。这样的操作直到所有数字串都处理完毕,就得到了所求的最小数。证毕。“
#include <iostream> #include <cstdio> #include <string> #include <algorithm> using namespace std; const int maxn = 10010; string str[maxn]; bool cmp(string a, string b) { return a + b < b + a; } int main() { int n; cin >> n; for (int i = 0;i < n;i++) cin >> str[i]; sort(str, str + n, cmp); string ans; for (int i = 0;i < n;++i) ans += str[i]; while (ans.size() != 0 && ans[0] == '0') ans.erase(ans.begin()); if (ans.size() == 0) cout << 0; else cout << ans; return 0; }
-
-
来源:https://blog.csdn.net/weixin_44073967/article/details/100822447