电子学会五级-贪心算法
电子学会五级-贪心算法
1 部分背包问题
https://www.luogu.com.cn/problem/P2240
#include<bits/stdc++.h>
using namespace std;
const int MAXN=105;
int n,t;
struct mvp{
int m;
int v;
float p;
};
mvp mvps[MAXN];
bool cmp(mvp mvp1,mvp mvp2){//按单价从高到底排序
return mvp1.p>mvp2.p;
}
float ans;
int main(){
cin>>n>>t;
for(int i=0;i<n;i++){
int m,v;
cin>>m>>v;
mvps[i].m=m;
mvps[i].v=v;
mvps[i].p=v*1.0/m;
}
sort(mvps,mvps+n,cmp);//优先装单价高的 按单价从高到底排序
for(int i=0;i<n;i++){//优先装单价高的
if(t>=mvps[i].m){//本次可以装完
t-=mvps[i].m;
ans+=mvps[i].v;
}else{//装不完 分割装一部分
ans+=mvps[i].v*1.0/mvps[i].m*t;
break;
}
}
cout<<fixed<<setprecision(2)<<ans;
}
2 排队接水
https://www.luogu.com.cn/problem/P1223
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n;
struct js{
int t;
int idx;
}jss[N];
long long ans,curT;
bool cmp(js js1,js js2){
return js1.t<js2.t;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>jss[i].t;
jss[i].idx=i;
}
sort(jss+1,jss+n+1,cmp);
for(int i=1;i<=n;i++){
cout<<jss[i].idx<<" ";
curT+=jss[i].t;
if(i!=n)
ans+=curT;
}
printf("\n%.2f",ans*1.0/n);
}
3 合并果子
https://www.luogu.com.cn/problem/P1090
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e4+5;
int n;
int a[MAXN];
int ans;
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);//从小到大排序
for(int i=1;i<n;i++){//从1开始循环
a[i]+=a[i-1];//从小到大合并,并且合并到大的
ans+=a[i];//累加两个数合并的结构到ans
//合并后的把a[i]放到a数组排序
for(int j=i+1;j<n&&a[j-1]>a[j];j++){
swap(a[j],a[j-1]);
}
}
cout<<ans;
return 0;
}
4 P1094 [NOIP2007 普及组] 纪念品分组
https://www.luogu.com.cn/problem/P1094
#include<bits/stdc++.h>
using namespace std;
const int N=3e4+5;
int a[N],w,n,ans;
/*
每个组至多有两件纪念品 可以有1个或有2个
从大到小排序 最大的和当前最小的组合,可以就2个,不可以就当前单独1个
*/
int main(){
cin>>w>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+n+1,greater<int>());//从大到小排序
int x=1,y=n-1;//x左边最大的 y右边最小的
while(x<=y){//直到x==y 时 说明已经找完
if(x!=y && a[x]+a[y]<=w){//x和y一起组合<w 并且x和y不是同一个 --同一个单独组成
x++;
y--;
ans++;
}else{
x++;
ans++;
}
}
cout<<ans;
}
5 P1208 [USACO1.3]混合牛奶 Mixing Milk
https://www.luogu.com.cn/problem/P1208
#include<bits/stdc++.h>
using namespace std;
const int M=5005;//最大5000个元素
int n,m,ans;
struct milk{
int p;//价格
int a;//数量
}mls[M];//定义结构体数组
bool cmp(milk m1,milk m2){//按单价从低到高排序
return m1.p<m2.p;
}
int main(){
cin>>n>>m;
for(int i=0;i<m;i++){//输入
cin>>mls[i].p>>mls[i].a;
}
sort(mls,mls+m,cmp);//排序
for(int i=0;i<m;i++){
if(n>=mls[i].a){//收购数量大于当前农户可提供数量
n-=mls[i].a;//收购当前农户 剩余数量
ans+=mls[i].p*mls[i].a;//累加收购需要的钱
}else{//收不完当前农户 只收需要收的 收完退出
ans+=mls[i].p*n;//累加收购需要的钱
break;
}
}
cout<<ans;
}
6 P1106 删数问题
https://www.luogu.com.cn/problem/P1106
#include<bits/stdc++.h>
using namespace std;
const int N=255;
int k,len;
char a[N];
/*
贪心策略
删除一个,在相对位置不变的情况下,应该删除相邻两个数字中前面数字较大的那个
例如:175438
7>5 删除7 --15438
5>4 删除5 --1438
4>3 删除4 --138
8>0 删除8 --13
*/
int main(){
cin>>a>>k;
len=strlen(a);
while(k){
//i=len-1时 i+1超边界,默认a[i+1]=0,前面没有可删除数字时 可以删除最后一个数字
for(int i=0;i<len;i++){
if(a[i]>a[i+1]){//找出a[i]>a[i+1]的数字 删除a[i]
for(int j=i;j<len;j++){//i后面所有数字左移 删除a[i]
a[j]=a[j+1];
}
len--;//删除了一位,舍去最后一位
break;//每次只删除一位,保证删左边位权高的
}
}
k--;
}
int start=0;
while(a[start]=='0' && start<len-1){//去除前导0
start++;
}
for(int i=start;i<len;i++){//输出
cout<<a[i];
}
}
7 P4995 跳跳
https://www.luogu.com.cn/problem/P4995
#include<bits/stdc++.h>
using namespace std;
const int N=305;
long long ans;
int n;
int a[N];
/*
贪心策略
每次尽可能最高
按从小到大排序 从最小跳到最高 再从最高跳到第2小.....
*/
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);//从小到大排序
bool flag=false;//区分是最小跳还是最高跳 默认false 从最小开始跳
int now=0,head=0,tail=n-1;//now从哪里跳 head跳完移动到下一个 tail 跳完移动到前一个
while(head<=tail){//最后2时 跳到其中一个 这两个指针相同 这时需要再跳到另外一个上面
if(!flag){//从小跳到高
ans+=pow(now-a[tail],2);//累加结果
now=a[tail];//记录本次高度
tail--;//指针前移
flag=true;//下次从高跳到低
}else{
ans+=pow(now-a[head],2);//累加结果
now=a[head];//记录本次高度
head++;//指针后移
flag=false;//下次从低跳到高
}
}
cout<<ans;
}
8 P4447 [AHOI2018初中组]分组
https://www.luogu.com.cn/problem/P4447
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=1e5+40;
//f录入的数 q[i] 记录i分组下一个填写的数 siz此分组数的个数 top分组数
int f[MAXN],n,ans=1e9,siz[MAXN],top,q[MAXN];
/*
思路:
排序后(从小到大排序)分组填充
二分查找 找到第一个大于等于本次待天数的分组 填入此分组
找不到 新建分组
4
1 2 2 3
*/
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&f[i]);
sort(f+1,f+n+1); q[0]=1e9+1;//从小到大排序
for(int i=1;i<=n;i++){
int l=0,r=top;//所有分组二分查找
while(l<r){//二分查找 具体填入哪个分组 找到待填入数相同 找下一个 --分组前面长后面短
int mid=(l+r+1)>>1;
if(f[i]>=q[mid]) l=mid;
else r=mid-1;
}
if(q[l]!=f[i]) siz[++top]=1,q[top]=f[i]+1;//新建分组
else siz[l]++,q[l]++;//数字不能相同 下一个数加1
}
for(int i=1;i<=top;i++) ans=min(ans,siz[i]);//找人数最少分组
printf("%d\n",ans);
return 0;
}
9 P5019 [NOIP2018 提高组] 铺设道路
https://www.luogu.com.cn/problem/P5019
#include<bits/stdc++.h>
using namespace std;
int n,d[1000001];
long long ans=0;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>d[i];
for(int i=2;i<=n;i++)
if(d[i]>d[i-1])
ans+=d[i]-d[i-1];//当前只需要铺设差,前面已经把本次免费铺设过了
cout<<ans+d[1];//第一个开始铺设前面的,顺便把同高度后面也铺设了
return 0;
}
P1080 [NOIP2012 提高组] 国王游戏
https://www.luogu.com.cn/problem/P1080
P1842 [USACO05NOV]奶牛玩杂技
https://www.luogu.com.cn/problem/P1842
5 小A的糖果
https://www.luogu.com.cn/problem/P3817
6 铺设道路
https://www.luogu.com.cn/problem/P5019
7 线段覆盖
https://www.luogu.com.cn/problem/P1803
8 陶陶摘苹果(升级版)
https://www.luogu.com.cn/problem/P1478
作者:newcode 更多资源请关注纽扣编程微信公众号
从事机器人比赛、机器人等级考试、少儿scratch编程、信息学奥赛等研究学习