贪心法讲解
例题
[ 一 ] 旅行家的预算
题目:
具体思路如下:
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; }