目录
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;
}