• 【天梯赛 - L2习题集】啃题(6 / 44)


    目录

    !L2-001 城市间紧急救援 - Dijkstra运用

    !L2-002 链表去重 - 链表模拟

    !L2-003 月饼 - 结构体+重载运算符+排序

    !L2-004 这是二叉搜索树吗?- 建二叉树模板题

    L2-005 集合相似度 - set容器去重应用

    L2-006 树的遍历 - 中后序遍历构建树+层序遍历

    !L2-007 家庭房产 - 并查集+结构体+排

    !L2-008 最长对称子串 - 字符串+暴力+双指

    getline和cin区别

    L2-009 抢红包 - 模拟+排序

    L2-010 排座位

    L2-011 玩转二叉树 - 前中序遍历构建树+层序遍历

    ✓L2-012 关于堆的判断 - 优先队列+哈希表


    !L2-001 城市间紧急救援 - Dijkstra运

    思路:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N=510;
    6. int n,m,s,d;
    7. int g[N][N];
    8. int dist[N],w[N],sumw[N],road[N],pre[N];
    9. int prt[N],cnt=0;
    10. bool st[N];
    11. void dijkstra()
    12. {
    13. memset(dist,0x3f,sizeof dist);
    14. dist[s]=0;
    15. sumw[s]=w[s]; //救援队数目
    16. road[s]=1; //最短路径的条数
    17. for(int i=0;i
    18. {
    19. int t=-1;
    20. for(int j=0;j
    21. if(!st[j]&&(t==-1||dist[j]
    22. t=j;
    23. st[t]=true;
    24. for(int j=0;j
    25. {
    26. if(dist[j]>dist[t]+g[t][j]) //选最短路径
    27. {
    28. dist[j]=dist[t]+g[t][j];
    29. road[j]=road[t]; //不理解
    30. sumw[j]=sumw[t]+w[j];
    31. pre[j]=t;
    32. }
    33. else if(dist[j]==dist[t]+g[t][j])
    34. {
    35. road[j]+=road[t]; //不理解
    36. if(sumw[j]
    37. {
    38. sumw[j]=sumw[t]+w[j];
    39. pre[j]=t;
    40. }
    41. }
    42. }
    43. }
    44. cout<' '<
    45. //把经过的点倒序输出
    46. cout<
    47. for(int i=d;i!=s;i=pre[i])
    48. prt[cnt++]=i;
    49. reverse(prt,prt+cnt);
    50. for(int i=0;i
    51. cout<<' '<
    52. }
    53. int main()
    54. {
    55. cin>>n>>m>>s>>d;
    56. for(int i=0;i>w[i];
    57. memset(g,0x3f,sizeof g);
    58. while(m--)
    59. {
    60. int a,b,c;
    61. cin>>a>>b>>c;
    62. g[a][b]=g[b][a]=c;
    63. }
    64. dijkstra();
    65. return 0;
    66. }

    !L2-002 链表去重 - 链表模拟

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. const int N=1e5+10;
    9. int head,n;
    10. int e[N],ne[N];
    11. bool st[N];
    12. int main()
    13. {
    14. cin>>head>>n;
    15. while(n--)
    16. {
    17. int idx,w,next;
    18. cin>>idx>>w>>next;
    19. e[idx]=w,ne[idx]=next;
    20. }
    21. vector<int>re,unre; //re存重复元素 unre存不重复元素
    22. for(int i=head;i!=-1;i=ne[i])
    23. {
    24. int x=abs(e[i]);
    25. if(!st[x])
    26. {
    27. st[x]=true;
    28. unre.push_back(i);
    29. }else re.push_back(i);
    30. }
    31. //输出去重的链表
    32. for(int i=0;isize();i++)
    33. {
    34. printf("%05d %d",unre[i],e[unre[i]]);
    35. if(i==unre.size()-1) puts(" -1");
    36. else printf(" %05d\n",unre[i+1]);
    37. }
    38. //输出删去的链表
    39. for(int i=0;isize();i++)
    40. {
    41. printf("%05d %d",re[i],e[re[i]]);
    42. if(i==re.size()-1) puts(" -1");
    43. else printf(" %05d\n",re[i+1]);
    44. }
    45. return 0;
    46. }

      

    !L2-003 月饼 - 结构体+重载运算符+排序

    思路:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. const int N=1010;
    9. int n;
    10. double d,res=0;
    11. struct node
    12. {
    13. double w,p;
    14. bool operator<(const node &t)const //按照单价由大到小排序
    15. {
    16. return p/w>t.p/t.w;
    17. }
    18. }a[N];
    19. int main()
    20. {
    21. cin>>n>>d;
    22. for(int i=0;i>a[i].w;
    23. for(int i=0;i>a[i].p;
    24. sort(a,a+n);
    25. for(int i=0;i0;i++)
    26. {
    27. if(a[i].w<=d)
    28. {
    29. d-=a[i].w;
    30. res+=a[i].p;
    31. }else
    32. {
    33. res+=a[i].p/a[i].w*d;
    34. break;
    35. }
    36. //这个办法很妙↓
    37. /*double r=min(d,a[i].w);
    38. d-=r;
    39. res+=a[i].p/a[i].w*r;*/
    40. }
    41. printf("%.2f\n",res);
    42. return 0;
    43. }

    !L2-004 这是二叉搜索树吗?- 建二叉树模板题

    思路:

    1. #include
    2. #include
    3. using namespace std;
    4. const int N=1010;
    5. int n,a[N];
    6. int p1[N],p2[N];
    7. int cnt1=0,cnt2=0;
    8. bool flag;
    9. typedef struct node
    10. {
    11. int data;
    12. node *l,*r;
    13. }node,*tree;
    14. tree create1(tree T,int x)
    15. {
    16. if(!T)
    17. {
    18. T=(tree)malloc(sizeof(node));
    19. T->l=nullptr,T->r=nullptr;
    20. T->data=x;
    21. }
    22. else
    23. {
    24. if(T->data>x) T->l=create1(T->l,x);
    25. else if(T->data<=x) T->r=create1(T->r,x);
    26. }
    27. return T;
    28. }
    29. tree create2(tree T,int x)
    30. {
    31. if(!T)
    32. {
    33. T=(tree)malloc(sizeof(node));
    34. T->l=nullptr,T->r=nullptr;
    35. T->data=x;
    36. }
    37. else
    38. {
    39. if(T->data<=x) T->l=create2(T->l,x);
    40. else if(T->data>x) T->r=create2(T->r,x);
    41. }
    42. return T;
    43. }
    44. void pre1(tree T)
    45. {
    46. if(!T) return;
    47. p1[cnt1++]=T->data;
    48. pre1(T->l);
    49. pre1(T->r);
    50. }
    51. void pre2(tree T)
    52. {
    53. if(!T) return;
    54. p2[cnt2++]=T->data;
    55. pre2(T->l);
    56. pre2(T->r);
    57. }
    58. void post(tree T)
    59. {
    60. if(!T) return;
    61. post(T->l);
    62. post(T->r);
    63. if(flag) cout<<' ';
    64. flag=true;
    65. cout<data;
    66. }
    67. int main()
    68. {
    69. cin>>n;
    70. for(int i=0;i>a[i];
    71. //创建二叉搜索树
    72. tree T1=nullptr;
    73. for(int i=0;icreate1(T1,a[i]);
    74. //创建镜像二叉搜索树
    75. tree T2=nullptr;
    76. for(int i=0;icreate2(T2,a[i]);
    77. //分非镜像和镜像进行前序遍历 和原序列进行比较
    78. pre1(T1),pre2(T2);
    79. bool f1=false,f2=false;
    80. for(int i=0;iif(p1[i]!=a[i]) f1=true;
    81. for(int i=0;iif(p2[i]!=a[i]) f2=true;
    82. if(f1&&f2) cout<<"NO";
    83. else if(!f1&&f2) puts("YES"),post(T1);
    84. else if(f1&&!f2) puts("YES"),post(T2);
    85. else if(!f1&&!f2) puts("YES"),post(T1);
    86. return 0;
    87. }

    L2-005 集合相似度 - set容器去重应用

    1. #include
    2. #include
    3. using namespace std;
    4. const int N=1e4+10;
    5. int n,m,k;
    6. int main()
    7. {
    8. set<int>s[N];
    9. cin>>n;
    10. for(int i=1;i<=n;i++)
    11. {
    12. cin>>m;
    13. while(m--)
    14. {
    15. int x;
    16. cin>>x;
    17. s[i].insert(x);
    18. }
    19. }
    20. cin>>k;
    21. while(k--)
    22. {
    23. int a,b,cnt=0;
    24. cin>>a>>b;
    25. for(auto x:s[a]) if(s[b].count(x)) cnt++;
    26. printf("%.2f%%\n",cnt*1.0/(s[a].size()+s[b].size()-cnt)*100);
    27. }
    28. return 0;
    29. }

    L2-006 树的遍历 - 中后序遍历构建树+层序遍历

    思路: 这题思路跟L2-011 玩转二叉树一模一样啊 就是板子题

    • 通过中后序构建树
    • 层序遍历
    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N=35;
    6. int n;
    7. int po[N],mid[N];
    8. typedef struct node
    9. {
    10. int data;
    11. node *l,*r;
    12. }node,*tree;
    13. tree reback(int len,int *po,int *mid) //通过中序和后序遍历还原前序遍历
    14. {
    15. if(len<=0) return NULL;
    16. tree T=(tree)malloc(sizeof(node));
    17. T->l=T->r=NULL;
    18. T->data=po[len-1]; //后序遍历的最后一个点为前序遍历根节点
    19. int i=0;
    20. for(i=0;i
    21. if(T->data==mid[i]) break; //在中序遍历里找到树根 记录i
    22. T->l=reback(i,po,mid);
    23. T->r=reback(len-1-i,po+i,mid+i+1);
    24. return T;
    25. }
    26. void bfs(tree T)
    27. {
    28. bool flag=false;
    29. queueq;
    30. q.push(T);
    31. while(q.size())
    32. {
    33. auto t=q.front();
    34. q.pop();
    35. if(flag) cout<<' ';
    36. flag=true;
    37. cout<data;
    38. if(t->l)q.push(t->l);
    39. if(t->r)q.push(t->r);
    40. }
    41. }
    42. int main()
    43. {
    44. cin>>n;
    45. for(int i=0;i>po[i];
    46. for(int i=0;i>mid[i];
    47. tree T=reback(n,po,mid);
    48. bfs(T);
    49. return 0;
    50. }

    !L2-007 家庭房产 - 并查集+结构体+排

    1. #include
    2. using namespace std;
    3. const int N=1e5+10;
    4. int n;
    5. int f[N];
    6. map<int,bool>st;
    7. struct peo
    8. {
    9. int id;
    10. double cnt,area;
    11. }p[N];
    12. struct family
    13. {
    14. int anc=-1,num;
    15. double cnt,area,avg_cnt,avg_area;
    16. }fam[N];
    17. int find(int x)
    18. {
    19. if(x!=f[x]) f[x]=find(f[x]);
    20. return f[x];
    21. }
    22. void unite(int a,int b)
    23. {
    24. int x=find(a);
    25. int y=find(b);
    26. if(x!=y) f[x]=y;
    27. }
    28. bool cmp(family a,family b) //家庭信息首先按人均面积降序输出,若有并列,则按成员编号的升序输出。
    29. {
    30. if(a.avg_area!=b.avg_area)
    31. return a.avg_area>b.avg_area;
    32. else return a.anc
    33. }
    34. int main()
    35. {
    36. for(int i=0;i
    37. cin>>n;
    38. for(int i=0;i
    39. {
    40. int id,fa,ma;
    41. cin>>id>>fa>>ma;
    42. st[id]=true;
    43. if(fa!=-1) st[fa]=true,unite(id,fa);
    44. if(ma!=-1) st[ma]=true,unite(id,ma);
    45. int k;
    46. cin>>k;
    47. while(k--)
    48. {
    49. int x;
    50. cin>>x;
    51. unite(x,id);
    52. st[x]=true;
    53. }
    54. int cnt,area;
    55. cin>>cnt>>area;
    56. p[id].cnt=cnt,p[id].area=area;
    57. }
    58. for(auto x:st)
    59. {
    60. fam[find(x.first)].cnt+=p[x.first].cnt;
    61. fam[find(x.first)].area+=p[x.first].area;
    62. if(fam[find(x.first)].anc==-1) fam[find(x.first)].anc=x.first;
    63. fam[find(x.first)].num++;
    64. }
    65. for(int i=0;i
    66. {
    67. if(!st[i])continue;
    68. fam[find(i)].avg_cnt=fam[find(i)].cnt/fam[find(i)].num;
    69. fam[find(i)].avg_area=fam[find(i)].area/fam[find(i)].num;
    70. }
    71. int sum=0;
    72. for(int i=0;iif(fam[i].num) sum++;
    73. cout<
    74. sort(fam,fam+N,cmp);
    75. for(int i=0;i
    76. printf("%04d %d %.3f %.3f\n",fam[i].anc,fam[i].num,fam[i].avg_cnt,fam[i].avg_area);
    77. return 0;
    78. }

    !L2-008 最长对称子串 - 字符串+暴力+双指

    getline和cin区别


    getline——按行读取, 一次读取多个字符,直到读满N个(不包括空白符)为止。
    形式:getline(字符指针,字符个数N,结束符);

    cin——遇到结束符(包括空白符)会终止,只读取空白符之前的部分。

    1. #include
    2. using namespace std;
    3. const int N=1e5+10;
    4. int main()
    5. {
    6. int res=0;
    7. string s;
    8. getline(cin,s); //不能用cin cin遇到空格就截止
    9. for(int i=0;isize();i++)
    10. for(int j=s.size()-1;j>=i;j--)
    11. {
    12. int l=i,r=j;
    13. while(l<=r&&s[l++]==s[r--])
    14. if(l>r) res=max(res,j-i+1);
    15. }
    16. cout<
    17. return 0;
    18. }
    1. #include
    2. using namespace std;
    3. string s;
    4. int main()
    5. {
    6. getline(cin,s);
    7. for(int len=s.size();len>0;len--) //找最大长度 倒序找
    8. for(int l=0;l+len-1size();l++)
    9. {
    10. bool f=false;
    11. int i=l,j=l+len-1;
    12. while(i
    13. {
    14. if(s[i]!=s[j])
    15. {
    16. f=true;
    17. break;
    18. }
    19. i++,j--;
    20. }
    21. if(!f)
    22. {
    23. cout<
    24. return 0;
    25. }
    26. }
    27. }

    L2-009 抢红包 - 模拟+排序

    思路:

    1. #include
    2. using namespace std;
    3. const int N=1e4+10;
    4. struct node
    5. {
    6. int id;
    7. double qiang_w,fa_w,res;
    8. int qiang_count;
    9. }a[N];
    10. bool cmp(node a,node b)
    11. {
    12. if(a.res!=b.res) return a.res>b.res;
    13. else if(a.qiang_count!=b.qiang_count) return a.qiang_count>b.qiang_count;
    14. else return a.id
    15. }
    16. int main()
    17. {
    18. int n;
    19. cin>>n;
    20. for(int i=1;i<=n;i++) a[i].id=i;
    21. for(int i=1;i<=n;i++)
    22. {
    23. int k;
    24. cin>>k;
    25. for(int j=1;j<=k;j++)
    26. {
    27. int id,w;
    28. cin>>id>>w;
    29. a[id].qiang_w+=w;
    30. a[id].qiang_count++;
    31. a[i].fa_w+=w;
    32. }
    33. }
    34. for(int i=1;i<=n;i++) a[i].res=a[i].qiang_w-a[i].fa_w;
    35. sort(a+1,a+n+1,cmp);
    36. for(int i=1;i<=n;i++) printf("%d %.2f\n",a[i].id,a[i].res*1.0/100);
    37. return 0;
    38. }

    L2-010 排座位

    思路:

    1. #include
    2. using namespace std;
    3. const int N=110;
    4. int g[N][N];
    5. int n,m,k;
    6. bool check(int a,int b)
    7. {
    8. for(int i=1;i<=n;i++)
    9. if(g[a][i]==1&&g[b][i])
    10. return true;
    11. return false;
    12. }
    13. int main()
    14. {
    15. cin>>n>>m>>k;
    16. while(m--)
    17. {
    18. int a,b,r;
    19. cin>>a>>b>>r;
    20. g[a][b]=g[b][a]=r;
    21. }
    22. while(k--)
    23. {
    24. int a,b;
    25. cin>>a>>b;
    26. if(g[a][b]==1) puts("No problem");
    27. else if(g[a][b]==0) puts("OK");
    28. else if(g[a][b]==-1&&check(a,b)) puts("OK but...");
    29. else puts("No way");
    30. }
    31. return 0;
    32. }

    L2-011 玩转二叉树 - 前中序遍历构建树+层序遍历

    思路: 和L2-006 树的遍历一模一样

    • 先通过中序遍历和前序遍历确定出树  因为题目要求左右子树对调 所以递归构建的时候反一下就可以了
    • 然后用队列进行层序遍历 根节点入队 然后根节点的左右结点入队 每次取队头输出然后扔掉
    1. #include
    2. using namespace std;
    3. const int N=55;
    4. int mid[N],pre[N];
    5. typedef struct node
    6. {
    7. int data;
    8. node *l,*r;
    9. }node,*tree;
    10. tree create(int len,int *mid,int *pre)
    11. {
    12. if(!len) return NULL;
    13. tree T=NULL;
    14. T=(tree)malloc(sizeof(struct node));
    15. T->l=T->r=NULL;
    16. T->data=pre[0]; //前序遍历的第一个是根节点
    17. int i=0;
    18. for(i=0;i//让i指针定位到中序遍历的根节点位置 !这里注意不能int i=0 要不然记录不了i值
    19. if(mid[i]==T->data) break;
    20. //因为要镜面翻转:左右子树互换
    21. T->r=create(i,mid,pre+1);
    22. T->l=create(len-(i+1),mid+i+1,pre+i+1);
    23. return T;
    24. }
    25. void bfs(tree T)
    26. {
    27. queueq;
    28. q.push(T);
    29. bool f=false;
    30. while(!q.empty())
    31. {
    32. auto t=q.front();
    33. q.pop();
    34. if(f) cout<<' ';
    35. f=true;
    36. if(t->l) q.push(t->l);
    37. if(t->r) q.push(t->r);
    38. cout<data;
    39. }
    40. }
    41. int main()
    42. {
    43. int n;
    44. cin>>n;
    45. for(int i=0;i>mid[i];
    46. for(int i=0;i>pre[i];
    47. tree T=create(n,mid,pre);
    48. bfs(T);
    49. return 0;
    50. }

     

    ✓L2-012 关于堆的判断 - 优先队列+哈希表

    大顶堆:每个结点的值都大于等于其左右孩子结点的值;

    小顶堆:每个结点的值都小于等于其左右孩子结点的值。

     思路:

    • 用优先队列PriorityQueue来实现小顶堆
    • 把小顶堆转化为数组 并更改数组下标从1开始 这样idx/2就是父节点
    • 用map存 < 结点值,下标 >
    • 逐步实现四个查询步骤即可 详见代码
    1. import java.util.*;
    2. public class Main{
    3. public static void main(String[] args)
    4. {
    5. Scanner sc=new Scanner(System.in);
    6. int n=sc.nextInt(),m=sc.nextInt();
    7. Queueq=new PriorityQueue<>();
    8. Map mp=new HashMap<>();
    9. String s;
    10. for(int i=0;i
    11. q.offer(sc.nextInt());
    12. //把优先队列(小顶堆)转化到数组
    13. Integer[] t=q.toArray(new Integer[n]);
    14. int[] a=new int[n+1]; //因为索引从1开始 所以是n+1
    15. int cnt=1;
    16. //修改数组索引从1开始 这样idx/2就是父结点
    17. for(int i=0,j=1;i
    18. a[j++]=t[i].intValue();
    19. for(int i=1;i<=n;i++)
    20. {
    21. mp.put(a[i],cnt);
    22. cnt++;
    23. }
    24. sc.nextLine(); //接收回车
    25. while(m-->0)
    26. {
    27. boolean f=false;
    28. s=sc.nextLine();
    29. String[] str=s.split(" ");
    30. if(s.indexOf("root")!=-1)
    31. {
    32. int root=Integer.parseInt(str[0]);
    33. if(mp.get(root)==1) f=true;
    34. }else if(s.indexOf("siblings")!=-1)
    35. {
    36. int l=Integer.parseInt(str[0]);
    37. int r=Integer.parseInt(str[2]);
    38. l=mp.get(l);
    39. r=mp.get(r);
    40. if(l/2==r/2) f=true;
    41. }else if(s.indexOf("parent")!=-1)
    42. {
    43. int parent=Integer.parseInt(str[0]);
    44. int child=Integer.parseInt(str[5]);
    45. if(mp.get(child)/2==mp.get(parent)) f=true;
    46. }else{
    47. int child=Integer.parseInt(str[0]);
    48. int parent=Integer.parseInt(str[5]);
    49. if(mp.get(child)/2==mp.get(parent)) f=true;
    50. }
    51. if(f) System.out.println("T");
    52. else System.out.println("F");
    53. }
    54. }
    55. }

     

  • 相关阅读:
    【opencv】多版本安装
    华钜同创:亚马逊开店有哪些注意事项
    (附源码)springboot在线考试系统 毕业设计 160935
    milvus集合管理
    两天学会微服务网关Gateway-Gateway路由规则
    JSP+MySQL基于ssm的主题酒店管理系统
    特斯拉第三方应用开发指南(一)
    【Spring】Spring MVC 拦截器的使用
    一篇文章带你学懂Redis
    知识图谱从入门到应用——知识图谱推理:基础知识
  • 原文地址:https://blog.csdn.net/weixin_61639349/article/details/126463011