当前位置:   article > 正文

2023年第十四届蓝桥杯省赛C++B组【第四题:飞机降落】_蓝桥杯飞机降落问题

蓝桥杯飞机降落问题


 这道题在AcWing上面似乎数据有做加强,但是根据本蒟蒻的获奖情况来看,蓝桥杯全排列应该可以过。

全排列复杂度最高约为:10*10!,三千万左右。

可以得出的结论是,全排列能做的题目,深搜也一定能做。所以最好舍弃这种最笨的暴力,选择深搜。

TLE代码(全排列)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=11;
  4. int n,t[N],d[N],l[N],T,a[N];
  5. bitset<N>vis;
  6. inline int read(){
  7. int x=0;char ch=getchar();
  8. while(ch>'9' or ch<'0')ch=getchar();
  9. while(ch>='0' and ch<='9')x=(x<<3)+(x<<1)+(ch xor 48),ch=getchar();
  10. return x;
  11. }
  12. inline void work(){
  13. n=read();
  14. for(int i=1;i<=n;++i){
  15. t[i]=read();
  16. d[i]=read();
  17. l[i]=read();
  18. a[i]=n-i+1;
  19. }
  20. bool can=false;
  21. do{
  22. vis.reset();
  23. int now=1,nowtime=0;
  24. while(now<=n){
  25. //如果有一架飞机已经不能降落,则直接下一个排列
  26. for(int i=1;i<=n;++i)
  27. if(!vis[i] and nowtime>t[i]+d[i])goto nxt;
  28. //降落飞机
  29. for(int i=1;i<=n;++i)
  30. if(a[i]==now){
  31. now++;
  32. if(nowtime<t[i])nowtime=t[i];
  33. nowtime+=l[i];
  34. vis[i]=true;
  35. break;
  36. }
  37. }
  38. can=true;
  39. break;
  40. nxt:{};
  41. }while(prev_permutation(a+1,a+n+1));
  42. if(can)printf("YES\n");
  43. else printf("NO\n");
  44. }
  45. int main(){
  46. T=read();
  47. while(T--)work();
  48. return 0;
  49. }

用prev_permutation是因为感觉答案可能分布在后面的排列,所以用prev试试,显然我这是在做梦。

回归正题,首先画出解空间树。

可以发现每一次都可以任选一架飞机去降落,当然前提是这个飞机没有降落过,即

  1. void dfs(int now){
  2. for(int i=1;i<=n;++i)
  3. if(!vis[i]){
  4. vis[i]=true;
  5. dfs(now);
  6. }
  7. }

根据要题目要求,给递归加入需要携带的参数。

  1. void dfs(int cnt,int nowtime){
  2. if(can)return;//如果已经有一个排列完成任务,全部结束
  3. if(cnt==n){//所有飞机都成功降落
  4. can=true;
  5. return;
  6. }
  7. for(int i=1;i<=n;++i){
  8. if(!vis[i]){
  9. if(nowtime>t[i]+d[i])return;//这个飞机不能被降落,结束这一个分支(比全排列更优的地方)
  10. vis[i]=true;
  11. if(nowtime<t[i])dfs(cnt+1,t[i]+l[i]);//可能存在前一架飞机降落了,但是后一架飞机还没到的情况,要等到t[i]再继续
  12. else dfs(cnt+1,nowtime+l[i]);
  13. vis[i]=false;//递归结束,往前回溯
  14. }
  15. }
  16. }

AC代码(深度优先搜索)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=11;
  4. int n,T,t[N],d[N],l[N];
  5. bitset<N>vis;
  6. bool can;
  7. inline int read(){
  8. int x=0;char ch=getchar();
  9. while(ch>'9' or ch<'0')ch=getchar();
  10. while(ch>='0' and ch<='9')x=(x<<3)+(x<<1)+(ch xor 48),ch=getchar();
  11. return x;
  12. }
  13. void dfs(int cnt,int nowtime){
  14. if(can)return;
  15. if(cnt==n){
  16. can=true;
  17. return;
  18. }
  19. for(int i=1;i<=n;++i){
  20. if(!vis[i]){
  21. if(nowtime>t[i]+d[i])return;
  22. vis[i]=true;
  23. if(nowtime<t[i])dfs(cnt+1,t[i]+l[i]);
  24. else dfs(cnt+1,nowtime+l[i]);
  25. vis[i]=false;
  26. }
  27. }
  28. }
  29. inline void work(){
  30. n=read();
  31. for(int i=1;i<=n;++i)
  32. t[i]=read(),d[i]=read(),l[i]=read();
  33. vis.reset();
  34. can=false;
  35. dfs(0,0);
  36. if(can)printf("YES\n");
  37. else printf("NO\n");
  38. }
  39. int main(){
  40. T=read();
  41. while(T--)work();
  42. return 0;
  43. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/461810
推荐阅读
相关标签
  

闽ICP备14008679号