贪心与sort的妙用(洛谷p2240,洛谷p1223,洛谷p1803)

鼠鼠在写了几道题之后发现,这几道题类似,所以就想放一块一起总结一下,用的思想就是所谓的“贪心”,就是局部最优->总体最优,但我感觉这个概念其实比较抽象,所以直接看题。。

洛谷p2240:部分背包问题(洛谷p2240)-CSDN博客

这个讲过了,有需要的同学可以去看下。

洛谷p1223:P1223 排队接水 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这个题的思路就是,先让时间短的先接水,时间长的后接,自然而然的就得到了较短的平均时间,因为耗着时间越长的越后,他加的次数便越少,不知道有没有同学和我刚开始一样没搞清楚一个概念,他等待的时间=第一个人耗费的时间+第二个人耗费的时间+.......+他前一个人消耗的时间。所以接水时间长的要把它放到最后,那如何很方便的将他们都排序呢?

        很简单,创建一个数组(当一维数组装不下需要的数据时,我们便可以考虑封装结构体),然后直接sort(真好用)

代码:

#include<iostream>
#include<algorithm>
using namespace std;
struct people {
	int ID;
	long long time;
};
people a[1000];
bool cmp(people p1, people p2) {
	return p1.time < p2.time;
}
long long ti[1000];
int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		a[i].ID = i + 1;
		cin >> a[i].time;
	}
	sort(a, a + n, cmp);
	long long stime = 0;
	long long sumtime=0;
	for (int i = 0; i < n; i++)
	{
		cout << a[i].ID<<" ";
		stime += a[i].time;
		ti[i] = stime;
		sumtime += ti[i];
	}
	sumtime -= ti[n - 1];
	cout << "\n";

	printf("%.2f", 1.0 * sumtime / n);
	return 0;
}

注意一点,记得开long long,int不够,然后你如果float a=b/c;b和c是long long的话,例如b=5,c=2,a并不会等于2.5000000,而是2.0000000,因为他会除完之后先把末尾舍去,在赋给a,那我们可以采用float a=1.0*b/c这个办法解决。

洛谷p1803:P1803 凌乱的yyy / 线段覆盖 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这个题和上面两道思路区别不大,但我认为难想的一点在于找到最优解的过程没有前两道那么简单明了。

        如果所有比赛都没有冲突,那么就可以全部参赛,那如果有两个比赛有冲突了(两种情况):1.一个包含另一个,那么选哪个?结束的早的,方便我参加下一个比赛;2.时间上有重叠,同理,选择结束的早的,原因同上。递推下去,那意思就是说我只要每次都选择,结束的早的,永远对我最有利,有点类似于数学归纳法。

        那我们思路一样,用一个结构体封装起来,创一个数组,那按什么排序(sort)呢?结束早的排前边,然后创建一个整形记录此时的时刻,每进行完一个活动,看接下来的活动开始了没,开始了就下一个,没开始就参加

#include<iostream>
#include<algorithm>
using namespace std;
struct activity {
	int start;
	int end;
};
bool cmp(activity a1, activity a2) {
	return a1.end <= a2.end;
}
activity a[1000000];
int main() {
	int n;
	int ans = 0,finish=0;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i].start >> a[i].end;
	}
	sort(a, a + n, cmp);
	for (int i = 0; i < n; i++) {
		if (finish <= a[i].start) {
			ans++;
			finish = a[i].end;
		}
	}
	cout << ans;
	return 0;
}

如果有帮助还请点个赞,有问题的话可以评论捏

  • 22
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
洛谷P1004是洛谷网站上的一个题目,题目的链接为https://www.luogu.com.***大的总价值。具体的解题思路是使用贪心算法,每次选择最少的两堆果子进行合并,然后将合并后的果子插入到合适的位置,确保数组始终是升序排列。最后,输出合并的总价值。 对于给定的输入数据,可以使用以下步骤来解决这个问题: 1. 首先,读取输入的果子数量n和每堆果子的数量。 2. 将果子数量列表进行排序。 3. 初始化一个变量ans为0,用于记录合并的总价值。 4. 使用循环,直到果子数量列表的长度大于1: a. 选择列表中最少的两堆果子mnn和fruit进行合并。 b. 使用二分搜索找到合并后的果子应该插入的位置i。 c. 将合并后的果子的价值mnn加到ans中。 d. 更新果子数量列表,将合并的果子和剩余的果子分别放到对应的位置。 5. 输出ans,即合并的总价值。 下面是一个示例代码来解决这个问题: ```python def binary_search(arr, item): low = 0 high = len(arr) - 1 while low <= high: mid = int((low + high) / 2) guess = arr[mid] if guess < item: low = mid + 1 else: high = mid - 1 return low n = int(input()) fruit = [int(i) for i in input().split()] fruit.sort() ans = 0 while len(fruit) > 1: mnn = fruit fruit += mnn i = binary_search(fruit, mnn) ans += mnn fruit = fruit[2:i] + [mnn] + fruit[i:] print(ans) ``` 以上是一个使用贪心算法解决洛谷P1004题目的Python代码。希望能对你有帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [xml文件批量处理python脚本](https://download.csdn.net/download/caoxinri123/88239057)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [洛谷P1051Python写法(2种)](https://blog.csdn.net/NOIP_YYDS/article/details/122061345)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [洛谷 P1090 python](https://blog.csdn.net/weixin_52430436/article/details/122732587)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值