第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-966 自行车停放

举报
红目香薰 发表于 2023/02/20 16:57:38 2023/02/20
【摘要】 ​ ​编辑第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-966 自行车停放目录第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-966 自行车停放前言关于数学的疑问算法训练 自行车停放C语言C++语言Java语言Python语言总结第六届——第十三届省赛题解第六届——第十二届国赛题解前言        这段时间我会把蓝桥杯官网上的所有非VIP题目都发布一遍,让大家方便去搜...

 编辑

第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-966 自行车停放


目录

第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-966 自行车停放

前言

关于数学的疑问

算法训练 自行车停放

C语言

C++语言

Java语言

Python语言

总结

第六届——第十三届省赛题解

第六届——第十二届国赛题解



前言

        这段时间我会把蓝桥杯官网上的所有非VIP题目都发布一遍,让大家方便去搜索,所有题目都会有几种语言的写法,帮助大家提供一个思路,当然,思路只是思路,千万别只看着答案就认为会了啊,这个方法基本上很难让你成长,成长是在思考的过程中找寻到自己的那个解题思路,并且首先肯定要依靠于题海战术来让自己的解题思维进行一定量的训练,如果没有这个量变到质变的过程你会发现对于相对需要思考的题目你解决的速度就会非常慢,这个思维过程甚至没有纸笔的绘制你根本无法在大脑中勾勒出来,所以我们前期学习的时候是学习别人的思路通过自己的方式转换思维变成自己的模式,说着听绕口,但是就是靠量来堆叠思维方式,刷题方案自主定义的话肯定就是从非常简单的开始,稍微对数据结构有一定的理解,暴力、二分法等等,一步步的成长,数据结构很多,一般也就几种啊,线性表、树、图、再就是其它了。顺序表与链表也就是线性表,当然栈,队列还有串都是属于线性表的,这个我就不在这里一一细分了,相对来说都要慢慢来一个个搞定的。蓝桥杯中对于大专来说相对是比较友好的,例如三分枚举、离散化,图,复杂数据结构还有统计都是不考的,我们找简单题刷个一两百,然后再进行中等题目的训练,当我们掌握深度搜索与广度搜索后再往动态规划上靠一靠,慢慢的就会掌握各种规律,有了规律就能大胆的长一些难度比较高的题目了,再次说明,刷题一定要循序渐进,千万别想着直接就能解决难题,那只是对自己进行劝退处理。加油,平常心,一步步前进。

关于数学的疑问

蓝桥杯中涉及到的数学说多不多,说少也不少,这里罗列了一下能用到的,其中红色的是【大学C组】会使用到的

1、简单数学(基础运算)

2、位运算

3、线性代数

4、离散数学(组合数学)

5、初等数论(整数的性质)

6、概率论

7、几何

虽然看到了线性代数、离散数学、初等数论,但是对于C组来说不会考的太复杂,会基础就好。


算法训练 自行车停放

资源限制

内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s

问题描述

  有n辆自行车依次来到停车棚,除了第一辆自行车外,每辆自行车都会恰好停放在已经在停车棚里的某辆自行车的左边或右边。(e.g.停车棚里已经有3辆自行车,从左到右编号为:3,5,1。现在编号为2的第4辆自行车要停在5号自行车的左边,所以现在停车棚里的自行车编号是:3,2,5,1)。给定n辆自行车的停放情况,按顺序输出最后停车棚里的自行车编号。

输入格式

  第一行一个整数n。
  第二行一个整数x。表示第一辆自行车的编号。
  以下n-1行,每行3个整数x,y,z。
  z=0时,表示编号为x的自行车恰停放在编号为y的自行车的左边
  z=1时,表示编号为x的自行车恰停放在编号为y的自行车的右边

输出格式

  从左到右输出停车棚里的自行车编号

样例输入

4
3
1 3 1
2 1 0
5 2 1

样例输出

3 2 5 1

数据规模和约定

  n<=100000
  自行车编号为不超过100000的正整数

题解:

C语言

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define M 100007
#define ll long long
int lleft[M],rright[M];
void link(int l,int r){
	rright[l]=r;
	lleft[r]=l;
}
int main() {
	int i,n,x,y,z;
	scanf("%d%d",&n,&x);
	lleft[x]=0;
	rright[x]=0;
	int head=x;
	for(i=0;i<n-1;i++){
		scanf("%d%d%d",&x,&y,&z);
		int lx=lleft[x],rx=rright[x],ly=lleft[y],ry=rright[y];
		if(z==1){
			link(x,ry);
			link(y,x);
			if(x==head){
				head=y;
			}
		}
		else{
			link(ly,x);
			link(x,y);
			if(y==head){
				head=x;
			}
		}
	}
	printf("%d ",head);
	for(i=1;i<n;i++){
		printf("%d ",rright[head]);
		head=rright[head];
	}
	return 0;
}


C++语言

#include "stdio.h"

typedef struct
{

	long long int left;
	long long int right;

}cycle_line;
static cycle_line cycle_sort[100005];
int main()
{

	long long int n;
	long long int b;
	long long int i;
	long long int no;
	long long int no1;
	int way;


	for (i = 0; i < 100000; i++)
	{

		cycle_sort[i].right = -1;
		cycle_sort[i].left = -1;
	}
	scanf("%lld", &n);
	scanf("%lld", &b);

	for (i = 0; i < n - 1; i++)
	{
		scanf("%lld %lld %d", &no, &no1, &way);

		if (way == 0)
		{
			cycle_sort[no].right = no1;
			if (cycle_sort[no1].left != -1)
			{

				cycle_sort[no].left = cycle_sort[no1].left;
				cycle_sort[cycle_sort[no1].left].right = no;
				cycle_sort[no1].left = no;
			}
			else
			{
				cycle_sort[no1].left = no;

			}
		}
		else
		{
			cycle_sort[no].left = no1;

			if (cycle_sort[no1].right != -1)
			{

				cycle_sort[no].right = cycle_sort[no1].right;
				cycle_sort[cycle_sort[no1].right].left = no;
				cycle_sort[no1].right = no;
			}
			else
			{

				cycle_sort[no1].right = no;

			}

		}
	}

	while (cycle_sort[no].left != -1)
	{

		no = cycle_sort[no].left;
	}

	while (cycle_sort[no].right != -1)
	{
		printf("%lld ", no);
		no = cycle_sort[no].right;
	}
	printf("%lld", no);




	return 0;


}

Java语言

在扫描输入内容上会有不同的方法,但是与Scanner的用法是相同的。只是相对的录入速度快于Scanner这样在整体运算的过程中可以适当节约时间。


import java.io.*;
import java.lang.reflect.Array;
import java.util.*;


public class Main {
    /**
     * 双向链表的实现
     *
     * @author liyanan
     * @date 2020/1/2 13:16
     */
    public static class SNode<T> {
        /**
         * 存储数据
         */
        public T data;
        /**
         * 指向当前结点的前一个结点
         */
        public SNode<T> pre;
        /**
         * 指向当前结点的下一个节点
         */
        public SNode<T> next;

        public SNode() {
        }

        public SNode(T data) {
            this.data = data;
        }
    }

    public static class DoubleLinkedList<T> {

        /**
         * 双向链表的头结点,存储第一个有效结点的基地址
         */
        private SNode<T> head;

        /**
         * 双向链表的有效结点数量
         */
        private int size;

        public DoubleLinkedList() {
            head = null;
            size = 0;
        }

        public int getSize() {
            return size;
        }


        public boolean isEmpty() {
            return size == 0;
        }

        /**
         * 插入结点到双向链表末尾
         *
         * @param newNode
         */
        public void addLast(SNode<T> newNode) {
            if (isEmpty()) {
                head = newNode;
                head.next = null;
                head.pre = null;
                size++;
            } else {
                SNode<T> temp = head;
                // 找到双向链表最后一个有效结点
                while (temp.next != null) {
                    temp = temp.next;
                }
                // 将新结点加入双向链表
                addAfter(temp, newNode);
            }
        }

        /**
         * 将新的节点插入到指定节点后
         *
         * @param preNode 指定节点
         * @param newNode 新的节点
         */
        public void addAfter(SNode<T> preNode, SNode<T> newNode) {
            // 要插入到链表末尾时,不需要维护下一个结点的前驱指针
            if (preNode.next != null) {
                preNode.next.pre = newNode;
            }
            newNode.next = preNode.next;
            newNode.pre = preNode;
            preNode.next = newNode;
            size++;
        }
        /**
         * 将结点插入到新结点前
         */
        public void addPre(SNode<T> afterNode, SNode<T> newNode) {
            // 要插入到链表第一个结点时候,不用维护前一个的后继
            if (afterNode.pre != null) {
                afterNode.pre.next = newNode;
            } else head = newNode;
            newNode.pre = afterNode.pre;
            newNode.next = afterNode;
            afterNode.pre = newNode;
            size++;
        }
        /**
         * 删除数据域为指定值的元素
         *
         * @param e
         */
        public void del(T e) {
            SNode<T> temp = head;
            while (temp != null) {
                if (temp.data.equals(e)) {
                    // 维护 head,head 永远指向双向链表第一个有效结点
                    temp.next.pre = temp.pre;
                    if (temp == head) {
                        head = head.next;
                        head.pre = null;
                    } else {
                        temp.pre.next = temp.next;
                    }
                    return;
                }
                // temp 向后移
                temp = temp.next;
            }
        }

        /**
         * 删除指定位置的结点
         *
         * @param k
         */
        public void del(int k) {
            SNode<T> delNode = find(k);
            delNode.next.pre = delNode.pre;
            if (delNode == head) {
                head = head.next;
                head.pre = null;
            } else {
                delNode.pre.next = delNode.next.next;
            }
        }

        public SNode<T> findO(T x) {
            SNode<T>p = head;
            while (p != null && !p.data.equals(x)) p = p.next;
            assert p != null;
            return p;
        }

        /**
         * 找到双向链表第 k 个结点
         *
         * @param k k 从 0 开始
         * @return
         */
        public SNode<T> find(int k) {
            if (k > size || k < 0) {
                throw new RuntimeException("传入的参数 k 必须大于等于零并且小于等于链表的长度 size");
            }
            int cnt = 0;
            SNode<T> t = head;
            while (cnt != k) {
                cnt++;
                t = t.next;
            }
            return t;
        }

        /**
         * 打印单链表所有有效节点
         *
         * @return
         */
        public String printAll() {
            StringBuilder sb = new StringBuilder();
            SNode<T> temp = head;
            while (temp != null) {
                sb.append(temp.data);
                sb.append(" ");
                temp = temp.next;
            }
            return sb.toString();
        }
    }
     public static void main(String[] args) throws Exception{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
        HashMap<Integer, SNode<Integer>>loc = new HashMap<>();
        int n = Integer.parseInt(in.readLine());
        int x = Integer.parseInt(in.readLine());
        DoubleLinkedList<Integer> list = new DoubleLinkedList<>();
//        HashSet<Integer>set = new HashSet<>();
         SNode<Integer> cur = new SNode<>(x);
         loc.put(x, cur);
         list.addLast(cur);
        for (int i = 0; i < n - 1; i++) {
            String[] input = in.readLine().split(" ");
            int a = Integer.parseInt(input[0]);
            int b = Integer.parseInt(input[1]);
            int c = Integer.parseInt(input[2]);
            // b是已知结点,

            SNode<Integer> preNode = loc.get(b);
            cur = new SNode<>(a);
            loc.put(a, cur);
            if (c == 1) {
                // 把当前结点放在前一个结点的右边。
                list.addAfter(preNode, cur);
            }
            else {
                // 把当前结点放在前一个结点的左边
                list.addPre(preNode, cur);
            }
        }
//        out.write(list.printAll());
//         System.out.println();
        System.out.println(list.printAll());
    }
}

Python语言

相对简洁,但是需要对Python的一些语法很了解,特别是列表推导式的熟悉。

def insert(a, k):
    global index
    e[index] = a
    q[a] = index
    l[r[k]] = index
    r[index] = r[k]
    l[index] = k
    r[k] = index
    index += 1

N = 100010
e = [0] * N
l = [-1] * N
r = [-1] * N
l[1] = 0
r[0] = 1
q = [0] * N
n = int(input())
m = int(input())
index = 2
insert(m, 0)
for i in range(n - 1):
    a, b, c = map(int, input().split())
    if c == 0:
        insert(a, l[q[b]])
    else:
        insert(a, q[b])
i = r[0]
while i != 1:
    print(e[i], end=" ")
    i = r[i]




总结

没有什么不付出就能拿到的结果,我们都是在负重前行,最终结果与自身先天的脑力有一定的关系,但是还是有很大一部分看自己后天的努力,其实从报名到比赛也就5个月左右,真正刷题的事件也就2个月,2个月回忆一下你真正的认真刷过题吗,如果你真的用尽所有的精力去努力了,那么我相信你最终的成绩一定会让你满意的,加油。

第六届——第十三届省赛题解

所有的题目都做了讲解,最难的有配套的视频,视频提供者是【2020级的弓家宜】先生。

第六届Java省赛C组 https://laoshifu.blog.csdn.net/article/details/123284163
第七届Java省赛C组 https://laoshifu.blog.csdn.net/article/details/123285783
第八届Java省赛C组 https://laoshifu.blog.csdn.net/article/details/123302677
第九届Java省赛C组 https://laoshifu.blog.csdn.net/article/details/123303285
第十届Java省赛C组 https://laoshifu.blog.csdn.net/article/details/123319090
第十一届Java省赛C组 https://laoshifu.blog.csdn.net/article/details/123320205
第十二届Java省赛C组第一套 https://laoshifu.blog.csdn.net/article/details/123413141
第十二届Java省赛C组第二套 https://laoshifu.blog.csdn.net/article/details/123413271
第十三届Java省赛C组 https://laoshifu.blog.csdn.net/article/details/128891276

第六届——第十二届国赛题解

所有题目均有题解,部分第10题非最优解,至少跑20%数据。

第六届Java国赛C组 https://laoshifu.blog.csdn.net/article/details/123440705
第七届Java国赛C组 https://laoshifu.blog.csdn.net/article/details/123442982
第八届Java国赛C组 https://laoshifu.blog.csdn.net/article/details/123443626
第九届Java国赛C组 https://laoshifu.blog.csdn.net/article/details/123443908
第十届Java国赛C组 https://laoshifu.blog.csdn.net/article/details/123444946
第十一届Java国赛C组 https://laoshifu.blog.csdn.net/article/details/123445601
第十二届Java国赛C组 https://laoshifu.blog.csdn.net/article/details/123446589

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。