PTA-贪心(1070/1033/1037/1067/1038)

PTA-1070 Mooncake (25 分)

Mooncake is a Chinese bakery product traditionally eaten during the Mid-Autumn Festival. Many types of fillings and crusts can be found in traditional mooncakes according to the region’s culture. Now given the inventory amounts and the prices of all kinds of the mooncakes, together with the maximum total demand of the market, you are supposed to tell the maximum profit that can be made.

Note: partial inventory storage can be taken. The sample shows the following situation: given three kinds of mooncakes with inventory amounts being 180, 150, and 100 thousand tons, and the prices being 7.5, 7.2, and 4.5 billion yuans. If the market demand can be at most 200 thousand tons, the best we can do is to sell 150 thousand tons of the second kind of mooncake, and 50 thousand tons of the third kind. Hence the total profit is 7.2 + 4.5/2 = 9.45 (billion yuans).

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers N (≤1000), the number of different kinds of mooncakes, and D (≤500 thousand tons), the maximum total demand of the market. Then the second line gives the positive inventory amounts (in thousand tons), and the third line gives the positive prices (in billion yuans) of N kinds of mooncakes. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the maximum profit (in billion yuans) in one line, accurate up to 2 decimal places.

Sample Input:

3 200
180 150 100
7.5 7.2 4.5

Sample Output:

9.45

思路

最基础的贪心,每次在剩余种类中优先拿单位(百万元/吨)最高的种类。

#include<bits/stdc++.h>
using namespace std;
struct s
{
	double ton;
	double price;
};
s ans[1001];
bool cmp(s a,s b)
{
	double x,y;
	x=a.price/a.ton;
	y=b.price/b.ton;
	return x>y;
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++)
		cin>>ans[i].ton;
	for(int i=0;i<n;i++)
		cin>>ans[i].price;
	double sum=0;
	double tons=0;
	sort(ans,ans+n,cmp);
	for(int i=0;i<n;i++)
	{
		if(ans[i].ton<=m-tons)
		{
			tons+=ans[i].ton;
			sum+=ans[i].price;
		}
		else
		{
			sum+=(m-tons)*(ans[i].price/ans[i].ton);
			break;
		}
	}
	printf("%.2lf",sum);
	return 0;
}

PTA-1033 To Fill or Not to Fill (25 分)

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 where X 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

思路

将加油站按照距离排序后,将终点加到最后一个加油站,进行贪心策略:
计汽车能行驶的最远距离是maxway,显然,maxway=容量*每单位跑动距离
1.如果gas[0]<0,意味车无法开动,特判。
2.从当前加油站出发,向后遍历距离当前车站maxway距离的车站,代表能走到的车站。在这些车站里找到单位油钱价格最低的车站s:
1).如果s站价格比当前车站低,那么只需要走到s站即可,s站有更便宜的油,去s站加更多的油为最利。如果当前油箱里的油不够到s站,就在当前车站加够到s站的油即可,如果当前油量足够行驶到s站,直接行驶即可。
2).如果s站价格比当前车站高,那么当前车站即是汽车能跑动最远范围内最便宜的车站了,所以在当前车站加满油,再到跑动范围内相对最便宜的车站去加油为最利。
3.如果maxway范围内没有找到加油站,则汽车跑动的最远距离即是当前车站的距离+满油量跑动距离maxway;
如果最后遍历完后到了最后一个车站,即是到达终点输出总价;如果中途退出,输出距离。

#include<bits/stdc++.h>
using namespace std;
struct s
{
	double price;
	double dis;	
};
s gas[505];
bool cmp(s a,s b)
{
	return a.dis<b.dis;
}
int main()
{
	double ml,dis,per;
	int n;
	cin>>ml>>dis>>per>>n;
	for(int i=0;i<n;i++)
	{
		cin>>gas[i].price>>gas[i].dis;
	}
	gas[n].price=0;
	gas[n].dis=dis; 
	sort(gas,gas+n,cmp);
	double sum=0,oil=0;
	double maxway=ml*per;
	if(gas[0].dis!=0)
	{
		printf("The maximum travel distance = 0.00");
		return 0;
	}
	int i=0;
	while(i<n)
	{
		double mi=10000000;
		int go=0;
		for(int j=i+1;j<=n;j++)
		{
			if(gas[j].dis-gas[i].dis<=maxway)
			{
				if(gas[j].price<mi)
				{
					mi=gas[j].price;
					go=j;
					if(gas[j].price<gas[i].price) break;
				}
			}
		}
		if(!go)
		{
			break;
		}
		double need=(gas[go].dis-gas[i].dis)/per;
		if(mi<=gas[i].price)
		{
			if(oil<need)
			{
				sum+=(need-oil)*gas[i].price;
				oil=0;
			}
			else
			{
				oil-=need;
			}
		}
		else
		{
			sum+=(ml-oil)*gas[i].price;
			oil=ml-need;
		}
		i=go;
	}
	if(i!=n) printf("The maximum travel distance = %.2lf",gas[i].dis+per*ml);
	else printf("%.2lf",sum);
	return 0;
}

PTA-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 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 N C, followed by a line with N Ccoupon integers. Then the next line contains the number of products N P, followed by a line with NPproduct values. Here 1≤NC,NP≤105, 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

思路

样例:4x7+2x6+(-1)x(-3)=43
最大正数相乘+最小负数相乘,配对相加即可。

#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
	return a>b;
}
int main()
{
	int n,m;
	cin>>n;
	vector<int> wap,pro;
	int x=0,y=0,x1=0,y1=0;
	for(int i=0;i<n;i++)
	{
		int s;
		cin>>s;
		if(s>=0) x++;
		else y++;
		wap.push_back(s);
	}
	cin>>m;
	for(int i=0;i<m;i++)
	{
		int s;
		cin>>s;
		if(s>=0) x1++;
		else y1++;
		pro.push_back(s);
	}
	sort(wap.begin(),wap.end(),cmp);
	sort(pro.begin(),pro.end(),cmp);
	long long int tot=0;
	for(int i=0;i<min(x,x1);i++)
	{
		tot+=wap[i]*pro[i];
	}
	sort(wap.begin(),wap.end());
	sort(pro.begin(),pro.end());
	for(int i=0;i<min(y,y1);i++)
	{
		tot+=wap[i]*pro[i];
	}
	printf("%lld",tot);
	return 0;
}

PTA-1067 Sort with Swap(0, i) (25 分)

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 (≤10
5
) 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

思路

只能交换0和某一个数,由此想到交换0和0所在下标即可还原一个数。
例如:4 0 2 1 3 交换0和0所在下标1-> 4 1 2 0 3,1归位不再移动。
但如果在一次交换中0回到原位0,则无法继续移动,所以我们利用一个变量nums来计数,nums的值为除0外不在本位的数的个数。
在交换过程中如果0回到了0,我们定义k=1,从下标为1位置向后遍历,遇到不在本位的数,与0交换即可,这样不会超时(暴力算法两个测试点超时)
nums计算除0外不在本位的数的个数最好,如果计算所有不在本位的个数(包括0),那么0在本位时的交换nums应该再加一,而0不在本位时的交换还需要特判0是否回到了0让nums再减1。

#include<bits/stdc++.h>
using namespace std;
int ans[100005];
int main()
{
	int n;
	cin>>n;
	int nums=0;
	for(int i=0;i<n;i++)
	{
		int s;
		cin>>s;
		if(s!=i&&i) nums++;
		ans[s]=i;
	}
	long long int times=0;
	int k=1;
	while(nums>0)
	{
		if(ans[0]==0) 
		{
			while(k!=n)
			{
				if(ans[k]!=k)
				{
					swap(ans[0],ans[k]);
					//nums++; nums用来表示除0外不在位置上的数 
					times++;
					break;
				}
				k++;
			}
		}
		while(ans[0]!=0)
		{
			swap(ans[0],ans[ans[0]]);//我写法错误的原因:交换之后不确定是否0也被换回去了,如果0被换回去,应该-2 
			nums--;
			times++;
		}	
	}
	printf("%lld",times);
	return 0;
}

PTA-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

思路

排序时将两个串拼接比较,如果a+b<b+a,说明a在前比较小,应该将a放在b的前面,最后输出时需要去掉所有前导零,如果都是0则输出0。

#include<bits/stdc++.h>
using namespace std;
bool cmp(string a,string b)
{
	return a+b<b+a;
}
int main()
{
	int n;
	cin>>n;
	vector<string> ans;
	for(int i=0;i<n;i++)
	{
		string s;
		cin>>s;
		ans.push_back(s);
	}
	sort(ans.begin(),ans.end(),cmp);
	string s;
	for(int i=0;i<n;i++)
	{
		s+=ans[i];
	} 
	while(!s.empty()&&s[0]=='0')
		s.erase(s.begin());
	if(s.empty()) cout<<"0";
	else cout<<s;
	return 0;
}

总结

贪心算法没有固定的模板,重点考察的是对具体问题具体分析的能力,将一道贪心问题清楚且优雅地写出来,还需要做题量的积累。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新西兰做的饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值