贪心算法刷题总结(洛谷)

目录

1.部分背包问题

2.排队接水

3.线段覆盖(ddl问题)

4.小A的糖果

5.删数问题

6.陶陶摘苹果(升级版)

7.跳跳! 


1.部分背包问题

P2240 【深基12.例1】部分背包问题 - 洛谷 | 计算机科学教育新生态 

https://www.luogu.com.cn/problem/P2240

看题目以为是背包 其实是贪心 反证法证明贪心

所有金币都可以分开,也就是说只要按照性价比最高的取一定得到的价值最大。

性价比就是这堆金币的价值除以重量。

只需要把这n堆金币按性价比排序就行了。

然后依次遍历,如果背包中剩余可以拿的重量大于等于这堆金币的重量,就全拿,否则直接装满。

#include<bits/stdc++.h>
using namespace std;
struct coin{
    int m,v;
}a[999];
bool cmp(coin x,coin y){
    return x.v*y.m>y.v*x.m;
} 
int main(){
    int n,t,i;
    float ans=0;
    cin>>n>>t;
    for(int i=0;i<n;i++){
        cin>>a[i].m>>a[i].v;
    }
    sort(a,a+n,cmp);
    for(i=0;i<n;i++){
        if(a[i].m>t)
        break;
        t-=a[i].m;
        ans+=a[i].v;}
    if(i<n){
        ans+=1.0*t/a[i].m*a[i].v;
    }
    printf("%.2f",ans);
    return 0;
 }

2.排队接水

P1223 排队接水 - 洛谷 | 计算机科学教育新生态 https://www.luogu.com.cn/problem/P1223

贪心策略:先让用时少的人去接水

画图找规律:sum+=i*p[n-i].time

#include<bits/stdc++.h>
using namespace std;
struct water{
    int num,time;
}p[9999]; 
bool cmp(water a,water b){
    if(a.time!=b.time)
    return a.time<b.time;
    return a.num<b.num;
}
int main(){
int n;
double sum;
double t;
p[0].time=0;
cin>>n; 
for(int i=1;i<=n;i++){
    cin>>p[i].time;
    p[i].num=i;
}
sort(p+1,p+n+1,cmp);
for(int i=1;i<=n;i++){
    cout<<p[i].num;
    cout<<" ";
    sum+=i*(p[n-i].time);
}
t=1.0*sum/n;
cout<<endl;
cout<<fixed<<setprecision(2)<<t<<endl;
return 0;
}

3.线段覆盖(ddl问题)

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

在一个数轴上有n条线段,现要选取其中k条线段使得这k条线段两两没有重合部分,问最大的k为多少。

最左边的线段放什么最好?

显然放右端点最靠左的线段最好,从左向右放,右端点越小妨碍越少

其他线段放置按右端点排序,贪心放置线段,即能放就放

#include<bits/stdc++.h>
using namespace std;
struct Match{
	int start;
	int end;
}c[999999];
bool cmp(Match a,Match b){
 return a.end<b.end;
} 
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>c[i].start>>c[i].end;
	}
	sort(c,c+n,cmp);
	int x=0;//x代表当前位置
	int cnt=0;
	for(int i=0;i<n;i++){
		if(x<=c[i].start){
			x=c[i].end;
			cnt++;
		}
	}
	cout<<cnt<<endl;
	return 0;
}

4.小A的糖果

P3817 小A的糖果 - 洛谷 | 计算机科学教育新生态  https://www.luogu.com.cn/problem/P3817

当相邻的两盒大于x到时候,应该先吃那一盒呢?

答案:正着遍历,吃后面;反着遍历,吃前面(一举两得 符合至少的要求)

#include<bits/stdc++.h>
using namespace std;
int a[99999999];
int main(){
	int n,x;
	cin>>n>>x;
	long long ans=0;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=0;i<n-1;i++){
		if(a[i]+a[i+1]>x){
			ans+=a[i+1]+a[i]-x;
			a[i+1]=x-a[i];
		}
	}
	cout<<ans;
	return 0;
}

5.删数问题

P1106 删数问题 - 洛谷 | 计算机科学教育新生态  https://www.luogu.com.cn/problem/P1106

#include<bits/stdc++.h>
using namespace std;
string n;
int k;
string shanchu(int x){
    string s;
    for(int i=0;i<n.size();i++){
        if(i==x)
            continue;
            else
         s+=n[i];
    }
    return s;
}
void check(string x){
     if(x[0]=='0'){
       x=shanchu(0);  //删除前导0
     }
}
int main(){
    
    cin>>n;
    cin>>k;
    int cnt=0;
    int i=0;
    while(1){
    if(n[i]>n[i+1]){
        n=shanchu(i);
        check(n);
        i=0;
        cnt++;
        if(cnt==k)
        break;
    }
    else
    i++;
}
    for(int i=0;i<n.size();i++){
        cout<<n[i];
    }
	if(n.size()==0)
		cout<<0;
    return 0;
    }

6.陶陶摘苹果(升级版)

P1478 陶陶摘苹果(升级版) - 洛谷 | 计算机科学教育新生态  https://www.luogu.com.cn/problem/P1478

这种题和1、2、3题一样 先struct写性质 在写sort中cmp(排序规则)然后模拟+贪心

#include<bits/stdc++.h>
using namespace std;
struct apple{
	int xi,yi;
}ap[99999];
bool cmp(apple x,apple y){
	return x.yi<y.yi;
}
int main(){
	int n,s,a,b;
	int x1,y1;
	int cnt=0,ans=0;
	cin>>n>>s>>a>>b;
	for(int i=1;i<=n;i++){
		cin>>x1>>y1;
		if(x1<=a+b){
			cnt++;
			ap[cnt].xi=x1;
			ap[cnt].yi=y1;
		}
	}
	sort(ap+1,ap+1+cnt,cmp);
	for(int i=1;s>=ap[i].yi&&i<=cnt;i++){
		ans++;
		s-=ap[i].yi;
	}
	cout<<ans<<endl;
	return 0;
	}

7.跳跳! 

P4995 跳跳! - 洛谷 | 计算机科学教育新生态  https://www.luogu.com.cn/problem/P4995

贪心策略:最大最小之间来回跳

#include<bits/stdc++.h>
using namespace std;
long long n,a[310],ans;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+n+1);
	int q=0,p=n;
    a[0]=0;
	while(q<p){//最大最小来回跳
		ans+=pow((a[p]-a[q]),2);
		q++;
		ans+=pow((a[q]-a[p]),2);
		p--;
	}
	cout<<ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值