贪心法讲解
例题
[ 一 ] 旅行家的预算
题目:
具体思路如下:
1.如果不能到达,输出 -1
2.如果之后的序列中存在小于等于(注意取等号),找到第一个(证明:如果不是第一个最小值……),计算,加油到刚好到达目标点。
3.如果没有更小的,找到能到达的最小值,计算,加满油且没有越过终点。
代码见下:
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct Sto {
double Pri;
double Dist;
} Pot[9];
double Abt,v,Dist;
int n;
int main() {
scanf("%lf%lf%lf%lf%d",&Dist,&v,&Abt,&Pot[0].Pri,&n);
for(int i = 1; i<=n; i++) {
scanf("%lf%lf",&Pot[i].Dist,&Pot[i].Pri);
}
double Cost = 0,Now;
int End = 0;
for(int i = 0; i<n; i++) {
if(Pot[i].Pri > Pot[i + 1].Pri) {
Cost += (Pot[i + 1].Dist - Now * Abt - Pot[i].Dist) * Pot[i].Pri / Abt;
End = i + 1;
Now = 0;
} else {
double Max = v * Abt;
if(Max < Pot[i + 1].Dist - Pot[End].Dist) {
printf("No Solution");
return 0;
} else {
double Min = 1000;
int Idx = 0;
for(int j = i + 1; j<=n; j++) {
if(Pot[j].Dist - Pot[End].Dist > Max) {
break;
}
if(Pot[j].Pri < Min) {
Min = Pot[j].Pri;
Idx = j;
if(Min < Pot[End].Pri) {
break;
}
}
}
if(Min > Pot[End].Pri) {
Cost += (v - Now) * Pot[End].Pri;
Now = v - (Pot[Idx].Dist - Pot[End].Dist) / Abt;
if(Now * Abt >= Dist - Pot[Idx].Dist) {
Cost -= (Now * Abt - Dist + Pot[Idx].Dist) * Pot[End].Pri / Abt;
printf("%.2lf",Cost);
return 0;
}
} else {
Cost += (Pot[Idx].Dist - Now * Abt - Pot[End].Dist) * Pot[End].Pri / Abt;
Now = 0;
}
i = Idx - 1;
End = Idx;
}
}
}
Cost += (Dist - Pot[End].Dist - Now * Abt) * Pot[End].Pri / Abt;
printf("%.2lf",Cost);
return 0;
}
[ 二 ] 均分纸牌
题目:
具体思路:
1.先确定每堆牌应有的数量
2.将每堆牌数于平均值相减
3.做出来了
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int a[105];
int main() {
int n,Tot = 0;
scanf("%d",&n);
for(int i = 1; i<=n; i++) {
scanf("%d",&a[i]);
Tot += a[i];
}
Tot /= n;
int Ans = 0;
for(int i = 1; i<=n; i++) a[i] -= Tot;
for(int i = 1; i<=n; i++) {
if(a[i]) {
a[i + 1] += a[i];
Ans ++;
}
}
printf("%d",Ans);
return 0;
}
[ 三 ] 导弹拦截
题目:
具体思路:
1.每次都用最低的拦截器去拦截导弹
2.如果不够,新开一个,拦截高度定为当前高度
注:这里只给出了100分的做法(因为是贪心专题,就难得写了,重点在第二问)
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int High[100001][2], System[100001];
int main() {
int Amount = 0;
while (cin >> High[++Amount][0]) {
High[Amount][1] = 1;
};
Amount--;
for (int i = 2; i <= Amount; i++) {
int l = 0, k = 0;
for (int j = 1; j < i; j++) {
if (High[j][0] >= High[i][0] && High[j][1] > l) {
l = High[j][1];
}
}
if (l) {
High[i][1] = l + 1;
}
}
int maxn = 0;
for (int i = 1; i <= Amount; i++) {
maxn = max(maxn, High[i][1]);
}
printf("%d\n", maxn);
int Num = 0;
System[++Num] = 50001;
for (int i = 1; i <= Amount; i++) {
int minn = 50001,pos = 0;
for (int j = 1; j <= Num; j++) {
if (System[j] >= High[i][0] && System[j] <= minn) {
minn = System[j];
pos = j;
}
}
if (pos) {
System[pos] = High[i][0];
}
else {
System[++Num] = High[i][0];
}
}
cout << Num;
return 0;
}

浙公网安备 33010602011771号