贪心篇
贪心基本思路:
A.排序 当n=2时,算出结果,两数交换,比较怎么排列更优(国王的游戏)
B.如果不能排序,模拟最优选择的过程(旅行家的预算)
例1:奶牛晒衣服
题目背景
熊大妈决定给每个牛宝宝都穿上可爱的婴儿装 。但是由于衣服很湿,为牛宝宝晒衣服就成了很不爽的事情。于是,熊大妈请你(奶牛)帮助她完成这个重任。
题目描述
一件衣服在自然条件下用一秒的时间可以晒干 aa 点湿度。抠门的熊大妈只买了一台烘衣机 。使用用一秒烘衣机可以让一件衣服额外烘干 bb 点湿度(一秒晒干 a+ba+b 湿度),但在同一时间内只能烘一件衣服。现在有 nn 件衣服,第 ii 衣服的湿度为 w_iwi(保证互不相同),要你求出弄干所有衣服的最少时间(湿度为 00 为干 )。
输入格式
第一行三个整数,分别为 n,a,bn,a,b。
接下来 22 到 n+1n+1 行,第 ii 行输入 w_iwi。
输出格式
一行,弄干所有衣服的最少时间。
输入输出样例
输入 #1
3 2 1 1 2 3
输出 #1
贪心思路:
每天从剩下没干的衣服里选择一个最湿的,并排好序
#include<bits/stdc++.h> using namespace std; int w[1000]; int j; bool cmp(int a,int b) { return a>b; } int main() { int n,a,b; cin>>n>>a>>b; for(int i=1;i<=n;i++) cin>>w[i]; sort(w+1,w+n+1,cmp); int time=0; int p; while(1) { if(w[1]<=time*a) break; //如果这件衣服在自然条件下能干 就不用烘干了(因为之前在烘干其他衣服时候已经晾干过一会了) w[1]-=b; //烘干一天 p=w[1]; for(j=2;w[j]>p&&j<=n;j++) //因为都已经排好序了,所以如果 { w[j-1]=w[j]; //所有比当前衣服湿的都往前移 } w[j-1]=p; //把这件衣服放到合适的位置 time++; //过了一天 } cout<<time; return 0; }
例二:旅行家的预算
题目描述
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1D1、汽车油箱的容量CC(以升为单位)、每升汽油能行驶的距离D2D2、出发点每升汽油价格PP和沿途油站数NN(NN可以为零),油站ii离出发点的距离DiDi、每升汽油价格PiPi(i=1,2,…,Ni=1,2,…,N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
输入格式
第一行,D1D1,CC,D2D2,PP,NN。
接下来有NN行。
第i+1i+1行,两个数字,油站i离出发点的距离DiDi和每升汽油价格PiPi。
输出格式
所需最小费用,计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
输入输出样例
输入 #1
275.6 11.9 27.4 2.8 2 102.0 2.9 220.0 2.2
输出 #1
26.95
贪心思路:
先查找在自己最大能到达的范围中最小的加油站,然后在现在的加油站正好加够能到那个最便宜的加油站的油,
·如果有其他更便宜的加油站,在现在的加油站正好加够能到那个最便宜的加油站的油
·如果没有比目前的加油站更便宜的,那就从目前的加油站加满油,然后在从后面的加油站里选一个最便宜的
·如果没有比目前加油站更便宜的,但可以到达终点,就直接在目前的加油站里加够到终点的油直接结束
1 #include<bits/stdc++.h> 2 using namespace std; 3 double d[1000],pi[1000]; 4 int main() 5 { 6 double d1,c,d2,p,pz=0,pmin=10000,l=0;//l表示现在油箱里面还有多少油,pz表示钱数, 7 int n; 8 cin>>d1>>c>>d2>>p>>n; 9 pi[0]=p; 10 d[0]=0; 11 double x=c*d2; //x表示当油箱满的时候最多能走多少路 12 for(int i=1;i<=n;i++) 13 { 14 cin>>d[i]>>pi[i]; 15 } 16 for(int i=1;i<=n;i++) 17 { 18 if(d[i]-d[i-1]>x) //如果任意相邻的加油站之间的距离大于最多能走的路 就是无解 19 { 20 cout<<"No Solution"; 21 return 0; 22 } 23 } 24 double d0=0; //表示已经走了多少路 25 int ii=0; 26 while(d1-d0>0) //如果d1-d0=0 说明旅行家已经到了终点,直接退出 27 { 28 for(int i=ii+1;d[i]-d0<=x&&i<=n;i++) // 在范围之内 29 { 30 if(pi[i]<pmin) 31 { 32 pmin=pi[i]; 33 ii=i; 34 } 35 } 36 if(pmin<=p) //范围内的加油站比自己还便宜,那就使加的油刚好能支持到达这个加油站 37 { 38 pz+=((d[ii]-d0)/d2-l)*p;//(d[ii]-d0)/d2表示到收费最少的加油站需要的油一共多少升, 39 l=(d[ii]-d0)/d2; //灌满 40 } 41 else if(d1-d0>x)//这种情况指的是范围内的加油站都比自己贵,并且无法一次到达终点,所以应该在自己这个最便宜的加油站直接加满 42 { 43 pz+=(c-l)*p; 44 l=c; 45 } 46 else //这种情况 指的是范围内的加油站都比自己贵,但能一次到达终点,那我肯定不管后面加油站了,直接奔向终点 47 { 48 pz+=((d1-d0)/d2-l)*p; 49 break; //到了终点停止 50 } 51 l=l-(d[ii]-d0)/d2;//走多少里程,就相应地减去多少油 52 d0=d[ii];//更新d0,表示旅行家的移动 53 p=pmin;//更新p,方便下次进行比较 54 pmin=10000;//还原pmin,以便下次搜索最小值 55 } 56 printf("%.2lf",pz); 57 return 0; 58 }