第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-933 汉诺四塔

2023-02-23 13:42:30 浏览数 (1)

第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-933 汉诺四塔


目录

第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-933 汉诺四塔

前言

关于数学的疑问

算法训练 汉诺四塔

C语言

C 语言

Java语言

Python语言

总结

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

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


前言

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

关于数学的疑问

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

1、简单数学(基础运算) 2、位运算 3、线性代数 4、离散数学(组合数学) 5、初等数论(整数的性质) 6、概率论 7、几何

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


算法训练 汉诺四塔

资源限制

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

题目背景

  XJJ最近迷上了一款小游戏——汉诺四塔,但是由于智商有限,步骤多了容易手滑,于是他请求小伙伴们来帮他,人家才不是cheat呢。

游戏规则

  同汉诺塔相似,不过塔有4个,要求将盘子从塔1运到塔4。

输入格式

  一个数n表示盘子数。

输出格式

  第一行输出step表示你的操作步数。   接下来step行每行2个用空格隔开的数a,b表示将塔a最上面的盘子移到塔b。   你的输出只要保证能帮XJJ通关游戏即可,对步数没有太大要求,当然你操作100000步XJJ也会等不及的啦。

数据规模和约定

  6<=n<=30

题解:

C语言

代码语言:javascript复制
#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 pre[M],now[M],m=0;
void move3(int n,int a,int b,int c,int d) {
	if(n==1) {
		m  ;
		pre[m]=a,now[m]=d;    //当n只有1个的时候直接从a移动到c
	} else {
		move3(n-1,a,b,d,c);                    //第n-1个要从a通过c移动到b
		m  ;
		pre[m]=a,now[m]=d;	
		move3(n-1,c,b,a,d);         
	}
}
void move4(int n,int a,int b,int c,int d) {
	if(n==1) {
		m  ;
		pre[m]=a,now[m]=d;    //当n只有1个的时候直接从a移动到c
	} else {
		move4(n/2,a,c,d,b);                    //第n-1个要从a通过c移动到b
		move3(n-n/2,a,b,c,d);	
		move4(n/2,b,a,c,d);         
	}
}
int main() {
	int i,n;
	scanf("%d",&n);
	move4(n,1,2,3,4);
	printf("%dn",m);
	for(i=1;i<=m;i  ){
		printf("%d %dn",pre[i],now[i]);
	}
	return 0;
}

C 语言

代码语言:javascript复制
#include<iostream>
using namespace std;
typedef long long ll;
ll f[100],tx[100];
//f[x]=2*f[k-x] 2^k-1 
void Minmoves(int n)
{
	for(int i=1;i<=n;i  )
	{
		ll min=1000000000;
		for(int k=1;k<=i;k  )
		{
			if(min>2*f[i-k] (1<<k)-1)
			{
				min=2*f[i-k] (1<<k)-1;
				f[i]=min;
				tx[i]=k;
			}
		}
	}
}
int ans;
void move(int a,int b)
{
	cout<<a<<"  "<<b<<endl;
}
void Hanoi3(int n,int a,int b,int c)
{
	if(n==1)
	{
		move(a,c);return;
	}
	Hanoi3(n-1,a,c,b);
	move(a,c);
	Hanoi3(n-1,b,a,c);
}
void Hanoi4(int n,int a,int b,int c,int d)
{
	if(n==1)
	{
		move(a,d);return ;
	}
	int k=tx[n];
	Hanoi4(n-k,a,d,c,b);
	Hanoi3(k,a,c,d);
	Hanoi4(n-k,b,c,a,d);
} 
int main()
{
	int n;cin>>n;
	Minmoves(n);
	cout<<f[n]<<endl;
	Hanoi4(n,1,2,3,4);
	return 0;
} 

Java语言

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

代码语言:javascript复制
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static Map<Integer, int[]> memo = new HashMap<>();
    static List<Integer> s = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
    static List<Integer> s1 = new ArrayList<>();
    public static void main(String[] args)throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String reading = br.readLine();
        int n = Integer.parseInt(reading);
        f(n);
        System.out.println(memo.get(n)[1]);
        print_4(n, 1, 4);
    }

    public static int f(int n) {
        if (memo.containsKey(n)) {
            return memo.get(n)[1];
        }
        if (n == 1) {
            int value = 1;
            memo.put(n, new int[]{0, value});
            return value;
        }
        List<Integer> a = new ArrayList<>();
        for (int k = 1; k < n; k  ) {
            a.add(2 * f(n - k)   (int) Math.pow(2, k) - 1);
        }
        int value = Collections.min(a);
        int key = a.indexOf(value)   1;
        memo.put(n, new int[]{key, value});
        return value;
    }

    public static void print_4(int n, int p, int q) {
        if (n == 1) {
            System.out.println(p   " "   q);
            return;
        }
        List<Integer> b = new ArrayList<>(s);
        b.remove(Integer.valueOf(p));
        b.remove(Integer.valueOf(q));
        int a = memo.get(n)[0]; // 下面的盘数
        // 先把上面的盘子通过四柱移到2上
        print_4(n - a, p, b.get(0));
        s1 = new ArrayList<>(Arrays.asList(p, q, b.get(1)));
        print_3(a, p, q);
        print_4(n - a, b.get(0), q);
    }
    public static void print_3(int n, int p, int q) {
        if (n == 1) {
            System.out.println(p   " "   q);
            return;
        }
        List<Integer> a = new ArrayList<>(s1);
        a.remove(Integer.valueOf(p));
        a.remove(Integer.valueOf(q));
        print_3(n - 1, p, a.get(0));
        print_3(1, p, q);
        print_3(n - 1, a.get(0), q);
    }
}

Python语言

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

代码语言:javascript复制
import math
n=int(input())
d=[math.inf]*(n 1)
f=[math.inf]*(n 1)
d[0],f[0]=0,0
d[1],f[1]=1,1
q1=[0,1]
q2=[0,0]
def dh(j,first,second,third):
    if j==1:
        print(first,third)
    else:
        dh(j-1,first,third,second)
        print(first,third)
        dh(j-1,second,first,third)
def fh(n,first,second,third,fourth):
    if n==1:
        print(first,fourth)
    else:
        x1=q1[n]
        x2=q2[n]
        fh(x1,first,third,fourth,second)
        dh(x2,first,third,fourth)
        fh(x1,second,first,third,fourth)

for i in range(2,n 1):
    d[i]=2*d[i-1] 1
for i in range(2,n 1):
    for j in range(1,n):
        if f[i] > 2*f[j] d[i-j] :
            f[i]=f[j]*2 d[i-j]
            p1=j
            p2=i-j
    q1.append(p1)
    q2.append(p2)
    if i==n:
        print(f[n])
        

fh(n,1,2,3,4)

总结

没有什么不付出就能拿到的结果,我们都是在负重前行,最终结果与自身先天的脑力有一定的关系,但是还是有很大一部分看自己后天的努力,其实从报名到比赛也就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

0 人点赞