1. 程式人生 > >PAT甲級1037,1038解題報告

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 N​C​​, followed by a line with N​C​​ coupon integers. Then the next line contains the number of products N​P​​, followed by a line with N​P​​ product values. Here 1≤N​C​​,N​P​​≤10​5​​, and it is guaranteed that all the numbers will not exceed 2​30​​.

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 (≤10​4​​) 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;
}