贪心练习

问题 A: 看电视
按照结束时间排序,结束时间越早越排前。

#include <iostream>
#include <algorithm>
using namespace std;
int s[105], e[105];
int main()
{
	int n;
	while (1)
	{
		cin >> n;
		if (!n)
		{
			break;
		}
		for (int i = 0; i < n; i++)
		{
			cin >> s[i] >> e[i];
		}
		pair<int, int> p[105];
		for (int i = 0; i < n; i++)
		{
			p[i].first = e[i];
			p[i].second = s[i];
		}
		sort(p, p + n);
		int ans = 0, t = 0; 
		for (int i = 0; i < n; i++)
		{
			if (t <= p[i].second)
			{
				ans++;
				t = p[i].first;
			}
		}
		cout << ans << endl;
	}
	return 0;
} 

问题 B: 出租车费
这题其实只要找到一个分界点就行,在分界点处,决定是否将剩下的路程分两次坐出租车,那么怎么求呢?我们来分析一下:
首先,设路程x,0 < x <= 4时,价格是8,4 < x <= 8时, 价格是2 x + 2, 当 x > 8 时,价格是2.4 - 1.2。这三段区间路程的平均价格分别是 2.5、2、2.4,那么在第二段区间一定存在一个值使得当是剩下路程不分两次走时与分两次走时价格相等。列方程有:
2 x + 2 + 18 = 2.4 x - 1.2
x = 13
那么题目就简单了,当分两次使,x < 5 那么就不该分,否则就分。

# include<stdio.h>
int main()
{
	int n; 
	double s; 
	while (scanf("%d", &n) != EOF, n)
	{
		if (n <= 4)
		{
			printf("10\n"); 
			continue; 
		}
		s = n / 8 * 18; 
		n = n % 8; 
		if (!n) 
		{
			printf("%.lf\n", s); 
		}
		else if (n >= 5)
		{
			s += 2 + 2 * n; 
			printf("%.lf\n", s); 
			
		}
		else
		{
			s += 2.4 * n; 
			printf("%.1lf\n", s);
		}
	}
	return 0;
}

问题 C: To Fill or Not to Fill
① 首先增加一个目的地处的加油站,距离为目的地的距离,价格为0。题目要求最低价格那么先要考虑能不能到达目的地。有两种情况到不了目的地,第一种是所有的加油站距离都没有等于0的,那么说明车哪也去不了,直接输出并return;第二种是中途两个加油站之间的距离大于加满油后汽车能够行驶的最大距离,那么最大距离为当前加油站距离起点的距离加上汽车加满油能行驶最大距离。
② 那么我们来考虑一下最低价格。
i. 先要将加油站按照距离distant从小到大排序,然后寻找比当前加油站距离远的,并且在汽车加满油后能够行使到的范围内,比较油价。如果找到了更低的油价,就加油到刚好能跑到该加油站的油量(因为我们不想用更高的油价来跑)。
ii. 如果找不到更低的,就找出当前加油站以外更低的加油站,然后在当前加油站加满油之后过去(因为当前加油站油最便宜了)。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int cmp(pair<double, double> a, pair<double, double> b)
{
	return a.second < b.second;
}
int main()
{
	double capacity, average;
	int distant, n;
	scanf("%lf%d%lf%d", &capacity, &distant, &average, &n);
	vector<pair<double, double> > v(n);
	for (int i = 0; i < n; i++)
	{
		scanf("%lf%lf", &v[i].first, &v[i].second);
	}
	v.push_back(make_pair(0, distant));
	sort(v.begin(), v.end(), cmp);
	double minPrice = 0, tank = 0;
	int flag = 1;
	if (v[0].second)
	{
		printf("The maximum travel distance = 0.00");
		return 0;
	}
	int i = 0;
	while (i < n)
	{
		if (v[i + 1].second - v[i].second > capacity * average)
		{
			flag = 0;
			printf("The maximum travel distance = %.2f", v[i].second + capacity * average);
			break;
		}
		else
		{
			if (v[i + 1].first <= v[i].first)
			{
				minPrice += ((v[i + 1].second - v[i].second) / average - tank) * v[i].first;
				tank = 0;
				i++;
			}
			else
			{
				int minIndex = i + 1;
				for (int j = i + 1; j < n && (v[j].second - v[i].second) <= capacity * average; j++)
				{
					if (v[minIndex].first >= v[j].first)
					{
						minIndex = j;
					}
				}
				if (v[i].first <= v[minIndex].first)
				{
					if (distant - v[i].second <= capacity * average)
					{
						minPrice += ((distant - v[i].second) / average - tank) * v[i].first;
						break;
					}
					else
					{
						minPrice += (capacity - tank) * v[i].first;
						tank = capacity - (v[minIndex].second - v[i].second) / average;
					}
				}
				else
				{
					minPrice += ((v[minIndex].second - v[i].second) / average - tank) * v[i].first;
					tank = 0;
				}
				i = minIndex;
			}
		}
	}
	if (flag)
	{
		printf("%.2f", minPrice);
	}
	return 0;
}

问题 D: Repair the Wall
这题只要从大到小排序,然后遍历数组,每次加上木板长度,然后判断用了几块木板时大于等于了裂缝长度就行啦。

#include <iostream>
#include <algorithm>
using namespace std;
int a[605];
int main()
{
	int l, n;
	while (scanf("%d%d", &l, &n) != EOF) 
	{
		for (int i = 0; i < n; i++)
		{
			cin >> a[i];
		}
		sort(a, a + n, greater<int>());
		int ans = 0, cur = 0, i = 0;
		while (cur < l && i < n)
		{
			cur += a[i];
			i++;
			ans++;
		}
		if (cur < l)
		{
			cout << "impossible" << endl;
		}
		else
		{
			cout << ans << endl; 
		}
	}
	return 0;
}

问题 E: FatMouse’s Trade
贪心水题。。

#include<cstdio>
#include<algorithm>
using namespace std;
struct room
{
	double j;
	double f;
	double p;
} r[1005];
bool cmp(room a, room b)
{
	return a.p > b.p;
}
int main()
{
	double m;
	int n;
	while (1)
	{
		scanf("%lf%d", &m, &n);
		if (m == -1 && n == -1)
		{
			break;
		}
		for (int i = 0; i < n; i++)
		{
			scanf("%lf%lf", &r[i].j, &r[i].f);
			r[i].p = r[i].j / r[i].f;
		}
		sort(r, r + n, cmp);
		double ans = 0;
		for (int i = 0; i < n; i++)
		{
			if (m >= r[i].f)
			{
				m -= r[i].f;
				ans += r[i].j;
			}
			else
			{
				ans += m * r[i].p;
				break;
			}
		}
		printf("%.3f\n", ans);
	}
	return 0;
}

问题 F: 迷瘴
水题。。

#include <iostream>
#include <algorithm>
using namespace std;
int main() 
{
	int m, n, v, w;
	cin >> m;
	while (m--) 
	{
		scanf("%d%d%d", &n, &v, &w);
		int a[105];
		for (int i = 0; i < n; i++) 
		{
			scanf("%d", &a[i]);
		}
		sort(a, a + n);
		int cnt = 0;
		double cur = 0;
		for (int i = 0; i < n; i++) 
		{
			double now = (cnt * cur + a[i]) / (cnt + 1.0);
			if (now <= w) 
			{
				cur = now;
				cnt++;
			}
			else
			{
				break;
			}
		}
		printf("%d %.2f\n", cnt * v, cur / 100);
	}
	return 0;
}

问题 F: 迷瘴
水。。

#include <iostream>
using namespace std;
int main()
{
	int n;
	int a[5] = {50, 20, 10, 5, 1};
	while (cin >> n)
	{
		int i = 0, b[55] = { 0 };
		while (n)
		{
			if (n >= a[i])
			{
				n -= a[i];
				b[a[i]]++;
			}
			else
			{
				i++;
			}
		}
		int flag = 1;
		for (int i = 55; i >= 0; i--)
		{
			if (b[i] && flag)
			{
				cout << i << "*" << b[i];
				flag = 0;
				continue;
			}
			if (b[i])
			{
				cout << "+" << i << "*" << b[i];
			}
		}
		cout << endl;
	}
	return 0;
}

PAT1023
分析:将数字0、数字1、……数字9的个数分别保存在数组a[i]中,因为0不能做首位,所以⾸首先将i从1到9输出第一个a[i]不为0的数字 i ,并将这个 i 保存在变量量 t 中,接着输出a[0]个0,最后输出a[t]-1个t(因为一个 t 已经被放在首位输出过一次了了),最后 i 从 t+1 到 9 输出 a[i] 个 i

#include <iostream>
#include <string>
using namespace std;
int main()
{
	int a[10];
	int t;
	for (int i = 0; i < 10; i++)
	{
		cin >> a[i];
	}
	for (int i = 1; i < 10; i++)
	{
		if (a[i] != 0)
		{
			cout << i;
			t = i;
			break;
		}
	}
	for (int i = 0; i < a[0]; i++)
	{
		cout << 0;
	}
	for (int i = 0; i < a[t] - 1; i++)
	{
		cout << t;
	}
	for (int i = t + 1; i < 10; i++)
	{
		for (int k = 0; k < a[i]; k++)
		{
			cout << i;
		}
	}
	return 0;
}

PAT1070
水。。

#include <iostream>
#include <algorithm>
#include <vector> 
using namespace std;
struct node{
	double total, price, unit;
};

int cmp(node a, node b)
{
	return a.unit > b.unit;
}
int main()
{
	int n, need;
	cin >> n >> need;
	vector<node> v(n);
	for (int i = 0; i < n; i++)
	{
		cin >> v[i].total;
	}
	for (int i = 0; i < n; i++)
	{
		cin >> v[i].price;
	}
	for (int i = 0; i < n; i++)
	{
		v[i].unit = v[i].price / v[i].total;
	}
	sort(v.begin(), v.end(), cmp);
	double ans = 0;
	for (int i = 0; i < n; i++)
	{
		if (v[i].total <= need)
		{
			ans += v[i].price;
			need -= v[i].total;
		}
		else
		{
			ans += v[i].unit * need;
			break;
		}
		
	}
	printf("%.2f", ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值