【算法1-5】贪心
煮啵觉得贪心是一种思维,不是一种模板(虽然有部分题感觉很模板)。煮啵觉得先确定序列,然后根据序列加工,输出即可。(煮波是蒟蒻,说错莫怪)
煮啵写的是洛谷题单【算法1-5】贪心 - 题单 - 洛谷,有兴趣可以看看(煮啵是两天写完的,为煮啵骄傲吧,玻璃心求夸哈) 自己点击看题哈,煮啵不喜欢刷字数
P2240 【深基12.例1】部分背包问题
P2240 【深基12.例1】部分背包问题 - 洛谷https://www.luogu.com.cn/problem/P2240煮啵觉得这是一道非常经典,一看就知道该用贪心的题
思路就是根据性价比重新排序,再计算sum
#include <iostream>
#include <algorithm>
#include<stdio.h>
using namespace std;
struct Item
{
int w;//重量
int v;//价值
};
Item item[101];//注意题目最多有100堆金币昂
bool cmp(Item a,Item b)
{
return (a.v*b.w>b.v*a.w);
//这里是(a.v/a.w>b.v/b.w) 除法转化转化成乘法,更精确
}
int main() {
int n,s;//煮啵这里习惯把s定义为总质量,n设置为个数
cin>>n>>s;
for(int i=0;i<n;i++)
{
cin>>item[i].w>>item[i].v;
}
sort(item,item+n,cmp);//性价比排序
double sum=0;
for(int i=0;i<n;i++)
{
if(s>=item[i].w)//s够
{
s-=item[i].w;
sum+=item[i].v;
}
else//s不够
{
sum+=(1.0*item[i].v/item[i].w)*s;
s=0;
break;
}
}
printf("%.2lf\n",sum);//听说printf比cout效率高捏
return 0;
}
P1223 排队接水
P1223 排队接水 - 洛谷https://www.luogu.com.cn/problem/P1223煮啵觉得这道题跟前一道思路差不多,先排序,再计算
#include <iostream>
#include <algorithm>
#include<stdio.h>
using namespace std;
struct Item
{
int t;//时间
int p;//人
};
Item item[1001];//注意题目最多有1000人昂
bool cmp(Item a,Item b)
{
return a.t<b.t;
}
int main() {
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>item[i].t;
item[i].p=i+1;
}
sort(item,item+n,cmp);//用时从短到长排序
long long sum=0;
//为什么用long long 呢,因为最多有1000人,
//最长时间为10^6,这样一算sum肯定超过10^9.3,所以噜
for(int i=0;i<n;i++)//不用等最后一个人
{
sum+=item[i].t*(n-i-1);
printf("%d ",item[i].p);
}
printf("\n");
printf("%.2lf\n",(double)sum/n);//听说printf比cout效率高捏
return 0;
}
煮啵因为不注意数据溢出,MC很多次了,可恶!!!!!
P1803 凌乱的yyy / 线段覆盖
https://www.luogu.com.cn/problem/P1803https://www.luogu.com.cn/problem/P1803
煮啵这题不会(惭愧),煮啵拿着s死命算,没算出来(小丑)。煮啵去看题解了,大佬果然是大佬,本蒟蒻拍手叫绝!!!
show time:这个题,先画时间数轴,发现了啥?这不是只要根据e排好序比较前一个时间段的e和后一个时间段的s不得了,而且第一个时间段的s不影响最终结果的呀!(完结撒花)
#include <iostream>
#include <algorithm>
#include<stdio.h>
using namespace std;
struct Item
{
int s;//开始时间
int e;//结束时间
};
Item item[1000001];//注意题目最多有10^6昂
bool cmp(Item a,Item b)
{
return a.e<b.e;
}
int main() {
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>item[i].s>>item[i].e;
}
sort(item,item+n,cmp);//按e从早到晚
int t=1;//第一段时间哈
int t_end=item[0].e;//记忆一下e的值,要跟下一个时间段的s对比的勒
for(int i=1;i<n;i++)
{
if(item[i].s>=t_end)
{
t++;
t_end=item[i].e;//更新
}
}
cout<<t<<endl;
return 0;
}
煮啵这里犯了一个致死的错误:
for(int i=1;i<n;i++)
{
注意这里//
int t_end=item[0].e;//记忆一下e的值,要跟下一个时间段的s对比的勒
if(item[i].s>=t_end)
{
t++;
t_end=item[i].e;//更新
}
}
煮啵把"int t_end=item[0].e;"循环初始化了(别骂了别骂了)
P1090 [NOIP 2004 提高组] 合并果子
P1090 [NOIP 2004 提高组] 合并果子 - 洛谷https://www.luogu.com.cn/problem/P1090这道题煮啵很喜欢,因为用到了新东西嘿嘿嘿(煮啵不是变态奥)
#include <iostream>
#include <queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
priority_queue<int,vector<int>,greater<int> > pq;//优先队列的小顶堆
int main() {
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int x;
cin>>x;
pq.push(x);//插入/优先队列
}
long long sum=0;
while(pq.size() > 1)
{
int a=pq.top();pq.pop();//读取顶堆元素后移除队列
int b=pq.top();pq.pop();
pq.push(a+b);//插入,解决要重排的问题(好爱好爱)
sum+=(a+b);
}
cout<<sum<<endl;//输出,deepseek说printf和cout在小范围没差qaq
}
煮啵觉得超重要:
push(x)
的作用
将
x
插入优先队列,并自动调整堆结构,保证堆的性质(最小的元素在堆顶)。
pq.pop()
的功能
移除堆顶元素:
在优先队列中,
pop()
会 删除队列顶部的元素(即优先级最高的元素)。如果优先队列是 小顶堆(
priority_queue<int, vector<int>, greater<int>>
),则pop()
会移除 最小的元素。如果优先队列是 大顶堆(默认
priority_queue<int>
),则pop()
会移除 最大的元素。调整堆结构:
删除堆顶元素后,优先队列会自动调整内部结构,使得新的堆顶元素仍然符合堆的性质(最小堆或最大堆)。
pq.top()
:访问堆顶元素(不删除)
返回优先队列的 堆顶元素(即当前优先级最高的元素)。
不删除元素,只读取它的值。
pq.empty()
:检查队列是否为空
返回
true
如果队列为空,否则返回false
。常用于循环终止条件 或 防止
top()/pop()
空队列访问。
pq.size()
:返回队列中的元素个数
返回当前优先队列中的 元素数量。
可用于判断是否还需要继续处理。
P3817 小A的糖果
P3817 小A的糖果 - 洛谷https://www.luogu.com.cn/problem/P3817煮啵这题,这题思路不够严谨,不够贪心。煮啵觉得自己很容易第一反应是这段代码,所以还是放出来吧。
#include <iostream>
#include <queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main() {
int n,x;
cin>>n>>x;
int arr[n];
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
long long sum=0;
for(int i=0;i<n-1;i++)
{
int a=0;//左边超值
int b=0;//右边超值
if(arr[i]>x)
{
a=arr[i]-x;
}
if(arr[i]+arr[i+1]>x)
{
b=arr[i+1]+arr[i]-x;
arr[i+1]=arr[i+1]-b;
}
sum+=(a+b);
}
if(arr[n-2]+arr[n-1]>x)
{
sum+=arr[n-2]+arr[n-1]-x;
}
cout<<sum<<endl;
}
煮啵 想的是,有事没事直接删右边,但是可能删左边是最优QAQ
煮啵调试了一波,自信又回来了
#include <iostream>
#include <queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int main() {
int n,x;
cin>>n>>x;
int arr[n];
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
long long sum=0;
for(int i=0;i<n-1;i++)
{
int a=0;//左边超值
int b=0;//右边超值
if(arr[i]>x)
{
a=arr[i]-x;
///注意这里/左边值要改变罢了
arr[i]=x;
}
if(arr[i]+arr[i+1]>x)
{
b=arr[i+1]+arr[i]-x;
arr[i+1]=arr[i+1]-b;
}
sum+=(a+b);
}
if(arr[n-2]+arr[n-1]>x)
{
sum+=arr[n-2]+arr[n-1]-x;
}
cout<<sum<<endl;
}