【数据结构与算法】学习笔记-《算法笔记》-11【贪心】

简单贪心

示例一:月饼
在这里插入图片描述
在这里插入图片描述

#include "stdafx.h"
#include <string>
#include <cstdio>
#include <algorithm>
using namespace std;

struct mooncake {
	double store;//库存量
	double sell;//总售价
	double price;//单价
}cake[1010];

bool cmp(mooncake a, mooncake b)
{
	return a.price > b.price;
}

int main()
{
	int n;
	double d;
	while (scanf("%d", &n) != EOF)
	{
		scanf("%lf", &d);
		for (int i = 0; i < n; i++)
		{
			scanf("%lf", &cake[i].store);
		}
		for (int i = 0; i < n; i++)
		{
			scanf("%lf", &cake[i].sell);
			cake[i].price = cake[i].sell / cake[i].store;
		}
		sort(cake, cake + n, cmp);
		double sum = 0;
		//double left = d;
		for (int i = 0; i < n; i++)
		{
			if (d > cake[i].store)
			{
				d -= cake[i].store;
				sum += cake[i].sell;
			}
			else
			{
				sum += cake[i].price*d;
				break;
			}
		}
		printf("%f\n", sum);
	}
}

区间贪心

示例二:区间不相交问题
在这里插入图片描述
我的代码:

#include "stdafx.h"
#include <cstdio>
#include <algorithm>
using namespace std;

bool hashTable[10];

struct interval {
	int left;
	int right;
}itv[10];

bool cmp(interval a, interval b)
{
	return a.left > b.left;
}

int main()
{
	int n, temp;
	while (scanf("%d", &n) != EOF)
	{
		temp = 0;
		for (int i = 0; i < n; i++)
		{
			scanf("%d%d", &itv[i].left, &itv[i].right);
			hashTable[i] = true;
		}
		sort(itv, itv + n, cmp);
		for (int i = 0; i < n - 1; i++)
		{
			for (int j = i+1; j < n; j++)
			{
				if (hashTable[j] == true)
				{
					if (itv[i].right <= itv[j].right)
					{
						hashTable[j] = false;
						//break;
					}
					else
						break;
				}
			}
		}
		for (int i = 0; i < n; i++)
		{
			i = temp;
			if (hashTable[i] == true)
			{
				for (int j = i+1; j < n; j++)
				{
					if (itv[j].right<=itv[i].left&&hashTable[j]==true)
					{
						temp = j;
						break;
					}
					else
					{
						hashTable[j] = false;
						temp = j + 1;
					}
				}
			}
		}
		for (int i = 0; i < n; i++)
		{
			if (hashTable[i] == true)
				printf("(%d,%d)\n", itv[i].left, itv[i].right);
		}
	}
	return 0;
}

比较书上的代码,我的cmp函数应该再添加如下语句:

if(a.x==b.x)//如果左端点与右端点相同
		return a.y<b.y;//按右端点从小到大排序

书上完整代码:

#include <cstdio>
#include <algorithm>
using namespace std;

struct interval {
	int left;
	int right;
}itv[10];

bool cmp(interval a, interval b)
{
	if(a.left!=b.left)
	return a.left > b.left;
	else return a.right < b.right;
}

int main()
{
	int n;
	while (scanf("%d", &n), n != 0)
	{
		for (int i = 0; i < n; i++)
		{
			scanf("%d%d", &itv[i].left, &itv[i].right);
		}
		sort(itv, itv + n, cmp);//区间排序ans记录不相交区间个数,lastX记录上一个被选中区间的左端点
		int ans = 1, lastX = itv[0].left;
		for (int i = 0; i < n; i++)
		{
			if (itv[i].right <= lastX)
			{
				lastX = itv[i].left;
				ans++;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

类似问题:区间选点问题
给出N个闭区间:[x,y],求最少需要确定多少个点,才能使每个闭区间中都至少存在一个点。
在这里插入图片描述

练习

看电视

题目描述
暑假到了,小明终于可以开心的看电视了。但是小明喜欢的节目太多了,他希望尽量多的看到完整的节目。
现在他把他喜欢的电视节目的转播时间表给你,你能帮他合理安排吗?
输入
输入包含多组测试数据。每组输入的第一行是一个整数n(n<=100),表示小明喜欢的节目的总数。
接下来n行,每行输入两个整数si和ei(1<=i<=n),表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。
当n=0时,输入结束。
输出
对于每组输入,输出能完整看到的电视节目的个数。
样例输入
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
样例输出
5

#include <cstdio>
#include <algorithm>
using namespace std;


struct interval {
	int left;
	int right;
}itv[110];

bool cmp(interval a, interval b)
{
	if(a.left!=b.left)
	return a.left > b.left;
	else return a.right < b.right;
}

int main()
{
	int n;
	while (scanf("%d", &n),n!=0)
	{
		for (int i = 0; i < n; i++)
		{
			scanf("%d%d", &itv[i].left, &itv[i].right);
		}
		sort(itv, itv + n, cmp);
		int ans = 1, lastX = itv[0].left;
		for (int i = 0; i < n; i++)
		{
			if (itv[i].right <= lastX)
			{
				lastX = itv[i].left;
				ans++;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

出租车费

题目描述
某市出租车计价规则如下:起步4公里10元,即使你的行程没超过4公里;接下来的4公里,每公里2元;之后每公里2.4元。行程的最后一段即使不到1公里,也当作1公里计费。
一个乘客可以根据行程公里数合理安排坐车方式来使自己的打车费最小。
例如,整个行程为16公里,乘客应该将行程分成长度相同的两部分,每部分花费18元,总共花费36元。如果坐出租车一次走完全程要花费37.2元。
现在给你整个行程的公里数,请你计算坐出租车的最小花费。
输入
输入包含多组测试数据。每组输入一个正整数n(n<10000000),表示整个行程的公里数。
当n=0时,输入结束。
输出
对于每组输入,输出最小花费。如果需要的话,保留一位小数。
样例输入
3
9
16
0
样例输出
10
20.4
36

#include <cstdio>
#include <algorithm>
using namespace std;

int main()
{
	int l;
	double cost = 0;
	double p = 25.0 / 6;
	double l0;
	while (scanf("%lf", &l0),l0!=0)
	{
		l = ceil(l0);
		int q = l / 8;
		int qq = l % 8;
		if (l / 8)
		{
			if (l % 8 <= p)
			{
				cost = l / 8 * 18 + l % 8 * 2.4;
			}
			if (l % 8 > p&&l % 8 <= 4)
			{
				cost = l / 12 * 18 + 10;
			}
			if (l % 8 > 4)
			{
				cost = l / 8 * 18 + 10 + (l % 8 - 4) * 2;
			}
		}
		else
		{
			if (l % 8 <= 4)	cost = 10;
			if (l % 8 > 4)	cost = 10 + (l - 4) * 2;
		}
		if (cost - floor(cost))
			printf("%.1lf\n", cost);
		else
			printf("%.0lf\n", cost);
	}
	return 0;
}

To Fill or Not to Fill这道题还不会做!!!

题目描述
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.
输入
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.
输出
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.
样例输入
59 525 19 2
3.00 314
3.00 0
样例输出
82.89

Repair the Wall

题目描述
Long time ago , Kitty lived in a small village. The air was fresh and the scenery was very beautiful. The only thing that troubled her is the typhoon.
When the typhoon came, everything is terrible. It kept blowing and raining for a long time. And what made the situation worse was that all of Kitty’s walls were made of wood.
One day, Kitty found that there was a crack in the wall. The shape of the crack is
a rectangle with the size of 1×L (in inch). Luckly Kitty got N blocks and a saw(锯子) from her neighbors.
The shape of the blocks were rectangle too, and the width of all blocks were 1 inch. So, with the help of saw, Kitty could cut down some of the blocks(of course she could use it directly without cutting) and put them in the crack, and the wall may be repaired perfectly, without any gap.
Now, Kitty knew the size of each blocks, and wanted to use as fewer as possible of the blocks to repair the wall, could you help her ?
输入
The problem contains many test cases, please process to the end of file( EOF ).
Each test case contains two lines.
In the first line, there are two integers L(0<L<1000000000) and N(0<=N<600) which
mentioned above.
In the second line, there are N positive integers. The ith integer Ai(0<Ai<1000000000 ) means that the ith block has the size of 1×Ai (in inch).
输出
For each test case , print an integer which represents the minimal number of blocks are needed.
If Kitty could not repair the wall, just print “impossible” instead.
样例输入
2 2
12 11
14 3
27 11 4
109 5
38 15 6 21 32
5 3
1 1 1
样例输出
1
1
5
impossible

#include <cstdio>
#include <algorithm>
using namespace std;

bool cmp(int a,int b)
{
	return a > b;
}

int main()
{
	int l, n;
	int len[610];
	while (scanf("%d%d", &l, &n) != EOF)
	{
		int count = 0;
		for (int i = 0; i < n; i++)
		{
			scanf("%d", &len[i]);
		}
		sort(len, len + n, cmp);
		for (int i = 0; i < n; i++)
		{
			count++;
			if (len[i] > l)
			{
				l -= len[i];
				break;
			}
			else
			{
				l -= len[i];
			}
		}
		if (l > 0)
			printf("impossible\n");
		else
			printf("%d\n", count);
	}
}

FatMouse’s Trade

题目描述
FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean.
The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and requires F[i] pounds of cat food. FatMouse does not have to trade for all the JavaBeans in the room, instead, he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food. Here a is a real number. Now he is assigning this homework to you: tell him the maximum amount of JavaBeans he can obtain.
输入
The input consists of multiple test cases. Each test case begins with a line containing two non-negative integers M and N. Then N lines follow, each contains two non-negative integers J[i] and F[i] respectively. The last test case is followed by two -1’s. All integers are not greater than 1000.
输出
For each test case, print in a single line a real number accurate up to 3 decimal places, which is the maximum amount of JavaBeans that FatMouse can obtain.
样例输入
4 2
4 7
1 3
5 5
4 8
3 8
1 2
2 5
2 4
-1 -1
样例输出
2.286
2.500

#include <string>
#include <cstdio>
#include <algorithm>
using namespace std;

struct roo {
	double j;
	double f;
	double price;
}r[1010];

bool cmp(roo a, roo b)
{
	return a.price < b.price;
}

int main()
{
	double m;
	int n;
	//int j[1010], f[1010];
	while (scanf("%lf%d", &m, &n) ,(m+1)+(n+1)!=0)
	{
		for (int i = 0; i < n; i++)
		{
			scanf("%lf%lf",&r[i].j,&r[i].f);
			r[i].price = r[i].f / r[i].j;
		}
		sort(r, r + n, cmp);
		double count = 0;
		for (int i = 0; i < n; i++)
		{
			if (m < r[i].f)
			{
				count += m / r[i].price;
				m = 0;
				break;
			}
			else
			{
				count += r[i].j;
				m -= r[i].f;
			}
		}
		printf("%.3lf\n", count);
	}
	return 0;
}

迷瘴(题目都没看懂)

找零钱

题目描述
小智去超市买东西,买了不超过一百块的东西。收银员想尽量用少的纸币来找钱。
纸币面额分为50 20 10 5 1 五种。请在知道要找多少钱n给小明的情况下,输出纸币数量最少的方案。 1<=n<=99;
输入
有多组数据 1<=n<=99;
输出
对于每种数量不为0的纸币,输出他们的面值数量,再加起来输出
样例输入
25
32
样例输出
20
1+51
20
1+101+12

#include "stdafx.h"
#include <vector>
#include <cstring>
#include <iostream>
#include<math.h>
#include<stdlib.h>
#include <string>
#include <cstdio>
#include <algorithm>
using namespace std;
int hashTable[5] = { 0 };

int main()
{
	int n;
	int price[5] = { 50,20,10,5,1 };
	int flag;
	while (scanf("%d", &n) != EOF)
	{
		memset(hashTable, 0, sizeof(hashTable));
		for (int i = 0; i < 5; i++)
		{
			if (n >= price[i])
			{
				n -= price[i];
				hashTable[i]++;
				i--;
			}
			if (n == 0)
			{
				flag = i;
				break;
			}
		}
		for (int i = 0; i < 5; i++)
		{
			if (hashTable[i] != 0)
			{
				printf("%d*%d", price[i], hashTable[i]);
				if (i != 4 && i <= flag)
					printf("+");
			}
		}
		printf("\n");
	}
	return 0;
}

这道题觉得比较有意思的写法是那个flag的设置,来控制“+”号的打印。

发布了43 篇原创文章 · 获赞 4 · 访问量 1213

猜你喜欢

转载自blog.csdn.net/weixin_42176221/article/details/101386687