PAT甲級1037,1038解題報告
1037 Magic Coupon (25 分)
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 Ntimes 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
題目大意:沒看懂那個核心單詞的意思,大概看到product應該是乘法的意思。看了下例子,大概就是兩個集合,每次各取一個相乘,得到的和累加得到最大值,每個值at most once,至多一次,潛臺詞就是可以不取。
解題思路:應該算是簽到題,就排個序,從大到小,大正數和大正數去乘,然後負數和負數,兩個最小的乘,這樣得到的值是最大的。
程式碼如下:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<time.h>
#include<math.h>
#include<set>
#include<list>
#include<climits>
#include<queue>
#include<cstring>
using namespace std;
int c[100005];
int p[100005];
bool cmp(int a, int b) {
return a > b;
}
int main()
{
int nc, np;
cin >> nc;
for (int i = 0; i < nc; i++) {
cin >> c[i];
}
cin >> np;
for (int i = 0; i < np; i++) {
cin >> p[i];
}
sort(c, c + nc, cmp);
sort(p, p + np, cmp);
int sum = 0;
int indexp=np-1;
int indexc=nc-1;
while (true) {
if (p[indexp] < 0 && c[indexc] < 0&&indexp>=0&&indexc>=0) {
sum += p[indexp] * c[indexc];
indexp--;
indexc--;
}
else break;
}
indexp = 0;
indexc = 0;
while (true) {
if (p[indexp] > 0 && c[indexc] > 0&&indexp<np&&indexc<nc) {
sum += p[indexp] * c[indexc];
indexp++;
indexc++;
}
else break;
}
cout << sum << endl;
return 0;
}
1038 Recover the Smallest Number (30 分)
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
題目大意:給一個字串集合,求它排列組合成的一個最小數字。
解題思路:和以前CF上不知UVA上做到的一個題目很像,本質和氣泡排序類似,也可以推匯出來,可以這樣思考,如果沒做過類似的也是可以想出來的,簡單來講,首先肯定考慮前置0的情況,前置0肯定是小的放前面,因為這樣可以讓位數少一位,然後再考慮沒有前置0的情況,肯定是第一位小的放前面,然後考慮相同第一位的情況,肯定是為了讓後面一個接上的第一個第一位小。。這樣依次思考,其實結論很簡介,無論你怎麼排列組合,你考慮的都是兩個字串進行比較,如果兩個字串交換了位置,這個數會不會變得更小。然後正好可以利用string按字典序的排列特性,可以得出排列函式,a+b<b+a,然後就沒什麼東西了,注意一下有個測試點是都是0的測試點就可以了。
程式碼如下:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<time.h>
#include<math.h>
#include<set>
#include<list>
#include<climits>
#include<queue>
#include<cstring>
using namespace std;
bool cmp(string a, string b) {
return a+b<b+a;
}
string getres(string *a,int n) {
string res="";
for (int i = 0; i < n; i++) {
res += a[i];
}
int count = 0;
for (int i = 0; i < res.size(); i++) {
if (res[i] != '0') {
break;
}
if (res[i] == '0') {
count++;
}
}
if (count == res.size())return "0";
else
return res.substr(count, res.size() - count);
}
string num[10005];
int main()
{
string res;
int N;
cin >> N;
for (int i = 0; i < N; i++) {
cin >> num[i];
}
sort(num, num + N, cmp);
if (N == 0)cout << 0 << endl;
else {
cout << getres(num, N) << endl;
}
return 0;
}