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

猜你喜欢

转载自blog.csdn.net/TateBrwonJava/article/details/83037962