算法复习之贪心
贪心法就是遵循某种规则,不断贪心地选取当前最优策略的算法设计方法
区间问题:(来自挑战程序设计竞赛)
有n项工作,每项工作分别在si时间开始,在ti时间结束。对于每项工作,可以选择参与与否,如果参与,那么自始至终必须全程参与。此外参与工作的时间段不能重叠(即使开始的瞬间和结束的瞬间重叠也不行)
求最多参与多少项工作。
算法:在可选的工作中,每次都选取结束时间最早的。
证明:与其他选择方案相比,该算法的选择方案在选取了相同数量的更早开始的工作时,其最终结束时间不会比其他方案的更晚
1 #include<iostream> 2 #include<utility> 3 #include<algorithm> 4 using namespace std; 5 const int MAX_N=100000; 6 int main() { 7 int N,S[MAX_N],T[MAX_N]; 8 pair<int,int> a[MAX_N]; 9 while(cin>>N) { 10 for(int i=0; i<N; i++) { 11 cin>>S[i]; 12 } 13 for(int i=0; i<N; i++) 14 cin>>T[i]; 15 for(int i=0; i<N; i++) { 16 a[i].first=T[i]; 17 a[i].second=S[i]; 18 } 19 sort(a,a+N); 20 int t=0,sum=0; 21 for(int i=0; i<N; i++) { 22 if(t<a[i].second) { 23 sum++; 24 t=a[i].first; 25 } 26 } 27 cout<<sum<<endl; 28 } 29 return 0; 30 } 31 32 //输入n=5,s={1,2,4,6,8},t={3,5,7,9,10}; 33 // 1=<N<=100000;1<=si<=ti<=10^9;
1 //在一维空间中告诉你N条线段的起始坐标与终止坐标,要求求出这些线段一共覆盖了多大的长度。 2 3 #include<iostream> 4 using namespace std; 5 int main() 6 { 7 int n; 8 while(cin>>n) 9 { 10 int *a=new int [n]; 11 int *b=new int [n]; 12 for(int i=0;i<n;i++) 13 cin>>a[i]; 14 for(int i=0;i<n;i++) 15 cin>>b[i]; 16 int len=b[0]-a[0]; 17 for(int i=1,j=0;i<n;i++) //i代表j之后的线段 18 { 19 if(a[i]>=b[j]) //如果第二条线段开始点大于第一条线段结束点 20 { 21 len+=b[i]-a[i]; 22 j=i; 23 } 24 //第二条开始点小于第一条结束点 25 else{ 26 if(b[i]<=b[j]) //第二条结束点小于第一条结束点 27 continue; 28 else{ 29 len+=b[i]-b[j]; 30 j=i; 31 } 32 } 33 } 34 cout<<len<<endl; 35 delete [] a; 36 delete [] b; 37 } 38 return 0; 39 }
一般先进行预处理,可能是排序或其他