P1803 洛谷 凌乱的yyy / 线段覆盖
题意:
给定每个比赛的起始时间和结束时间,蒟蒻不能同时参加两个或以上的比赛,问你如何安排能让他参加最多的比赛
分析:
可以说是比较明显的贪心题,或者dp题也行
贪心:::
按照结束时间从小到大排序,(因为你想参加最多的比赛 故 希望比赛尽早结束以便参加后面更多的比赛)
代码::
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll MOD=998244353; 5 const int maxn=1e6+5; 6 struct node 7 { 8 int from,to;//记录开始结束时间 9 }ma[maxn]; 10 bool cmp(node A,node B)//按结束时间从小到大排序 11 { 12 return A.to<B.to; 13 } 14 int main() 15 { 16 int n; 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++){ 19 int a,b; 20 scanf("%d%d",&ma[i].from,&ma[i].to); 21 } 22 sort(ma+1,ma+n+1,cmp); 23 int ans=0;//记录比赛次数 24 int pos=0;//记录结束时间 25 for(int i=1;i<=n;i++) 26 { 27 if(ma[i].from>=pos){ 28 ans++;//比赛时间不重叠 29 pos=ma[i].to;//记录本次比赛结束时间 30 } 31 } 32 printf("%d\n",ans); 33 return 0; 34 }
dp::
定义f[i]表示在前[i]场比赛中最多可以参加几场比赛,
由此得出方程:f[i]=max(f[i-1],f[temp]+1);
f[temp]指从f[i-1]向前找到的第一个允许参加第i场比赛的f[]
由于每次循环时都向前找一次temp会浪费太多时间,又因为f[]是单调递增的,
故可以令temp在循环时逐步递增,这样时间复杂度就降到了O(n).
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+5; 4 struct node{ 5 int l,r; 6 }ma[maxn]; 7 bool cmp(node a,node b){ 8 if(a.r!=b.r)return a.r<b.r; 9 return a.l<b.l; 10 } 11 int f[maxn]; 12 int main() 13 { 14 int n,temp; 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++) 17 scanf("%d%d",&ma[i].l,&ma[i].r); 18 sort(ma+1,ma+1+n,cmp); 19 f[0]=0; 20 temp=0; 21 for(int i=1;i<=n;i++){ 22 while(ma[temp+1].r<=ma[i].l)temp++; 23 f[i]=max(f[i-1],f[temp]+1); 24 } 25 printf("%d\n",f[n]); 26 return 0; 27 }
两代码跑的时间差不多!
不好的地方还请多多指教!!!!!
纵使单枪匹马,也要勇闯天涯