• 蓝桥杯训练3


    煤球数目

    • 有一堆煤球,堆成三角棱锥形。具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形), …
      如果一共有100层,共有多少个煤球?
      请填表示煤球总数目的数字。
      注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

    思路

    • 1 2 3 4 5 6……这一个等差数列的前n项和为(1+n)*n/2
    • 第1层的煤球数目为1
    • 第2层的煤球数目为1+2
    • 第3层的煤球数目为1+2+3
      ……
    • 第i层的煤球数组为(1+n)*n/2

    答案:171700
    Java的AC

    import java.util.Scanner;
    
    public class Main {
    
    	public static void main(String[] args) {
    		Scanner in =new Scanner(System.in);
    		int n=in.nextInt();
    		int sum=0;
    		for(int i=1;i<=n;i++) {
    			sum=sum+i*(i+1)/2;
    		}
    		System.out.println(sum);
    	}
    
    }
    

    python的AC

    a=int(input())	#a=101
    sum=0
    for i in range(a):
    	sum=sum+i*(i+1)/2
    print(sum)
    

    解数独

    编写一个程序,通过已填充的空格来解决数独问题。

    一个数独的解法需遵循如下规则:

    • 数字 1-9 在每一行只能出现一次。
    • 数字 1-9 在每一列只能出现一次。
    • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

    空白格用 ‘.’ 表示。
    在这里插入图片描述

    • 一个数独。
      在这里插入图片描述

    • 答案被标成红色。

    Note:

    • 给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
    • 你可以假设给定的数独只有唯一解。
    • 给定数独永远是 9x9 形式的。

    思路

    • 使用三个数组分别用于存储该行是否包含这个数,该列是否包含这个数,该宫里是否包含这个数,使用一个boolean变量用于判断是否找到了结果。需要先遍历一遍数组,填充上述三个数组,然后进行dfs,dfs的顺序是从左上角到右上角,一个一个遍历(依次向右遍历,如果到了本行最后一个就跳下一行第一个),终止条件就是已经到了第十行,说明前九行已经全部赋值结束。

    需要注意的是

    • 1.以前就有的值我们不能更改,要单独区分一下,这样的位置我们直接向后去判断即可。当我们dfs下一个位置结束后返回到该位置后,也会直接再返回前一个位置。
    • 2.当我们找到结果之后要将boolean变量赋值为true。此时dfs(9,0)就会返回到dfs(8,8),假如(8,8)本身就有值,那么就会继续返回(8,7),我们假设(8,7)本身没有值,是我们后添加的值,那么就会走到如下代码。我们要判断下究竟是(8,7)这个值不合适,还是已经找到了所有数独的解,如果是找到了所有数独的解就直接返回就行了,这样就会一直返回到dfs(0,0)的这里,然后返回。
     //这里可能是当前位置不能选取这个数,因为选取完这个数之后下一个位置的数无法找到合适的数
                    //也可能是当前的i和j下一个位置已经到达终点,然后return,就会走到这里
                    if(!find){
                    rows[i][num-1] = false;
                    columns[j][num-1] = false;
                    tables[table][num-1] = false;
                    board[i][j] = '.';
                    }else{
                        //如果找到了所有的值,dfs(9,0)就会将find置为true,然后返回dfs(8,8)的if(!find)这里,之后就会继续返回,直到返回dfs(0,0)的这里
                        return ;
    
    • 3.返回的两种情况:比如dfs(i,j)没有找到一个合适的数,或已经找到了所有数独(find=true)。就会返回至dfs(i,j-1),那么其中会有两种情况。
      • 1.如果(i,j-1)位置的为原本就有值的,就会继续返回dfs(i,j-2);
      • 2.如果没有值的话,就会走到if(!find)语句,去判断是舍弃(i,j-1)位置的值去寻找其他的值,还是已经找到结果继续向前返回。

    算法步骤

    • 数独首先行,列,还有 3*3 的方格内数字是 1~9 不能重复。
    • 声明布尔数组,表明行列中某个数字是否被使用了, 被用过视为 true,没用过为 false。
    • 初始化布尔数组,表明哪些数字已经被使用过了。
    • 尝试去填充数组,只要行,列, 还有 3*3 的方格内 出现已经被使用过的数字,我们就不填充,否则尝试填充。
    • 如果填充失败,那么我们需要回溯。将原来尝试填充的地方改回来。
    • 递归直到数独被填充完成。

    Java的AC

    class Solution {
        //该行是否包含这个数,rows[i][j]代表第i行是否有j+1这个数
        boolean[][]rows;
        //该列是否包含这个数,columns[i][j]代表第i列是否有j+1这个数
        boolean[][]columns;
        //这个宫里是否包含这个数tables[i][j]代表第i个宫是否有j+1这个数
        boolean[][]tables;
        char[][]board;
        boolean find = false; 
        public void solveSudoku(char[][] board) {
            this.board = board;
            rows = new boolean[9][9];
            columns = new boolean[9][9];
            tables = new boolean[9][9];
            for(int i = 0;i<9;i++)
            {
                for(int j = 0;j<9;j++)
                {
                    if(board[i][j]!='.')
                    {
                        int num = board[i][j]-'0';
                        rows[i][num-1] = true;
                        columns[j][num-1] = true;
                        tables[(i/3)*3+j/3][num-1] = true; 
                        }
                }
            }
            dfs(0,0);
        }
        //从0,0一直递归到8,8
        //一行一行递归,
        public void dfs(int i,int j)
        {
            //到了第10行(也就是说明第9行的第9个已经完成)
            if(i==9){
                //代表已经找到了结果
                find = true;
                return ;
            }
            //之前就不是的空格的数字我们不能改
            if(board[i][j]!='.')
                {
                     if(j==8)
                        //下一行
                        dfs(i+1,0);
                    else
                        //下一列
                        dfs(i,j+1);
                    //比如当执行完下一个返回到这里之后,就会执行出循环,返回上一个dfs循环
                    //假定都在一行,dfs(i,j)为之前就存在的数,那么执行完dfs(i,j+1)后就会返回这里,
                    //然后程序继续往下走就会跳出循环,然后返回到dfs(i,j-1)中。
                    }
                else{
                for(int num=1;num<10;num++)
                {
                    //第i行已经有num,或第j列已经有num
                    if(rows[i][num-1]||columns[j][num-1])
                        continue;
                    int table = (i/3)*3+j/3;
                    //第table个宫中已经有了num。
                    if(tables[table][num-1])
                        continue;
                    rows[i][num-1] = true;
                    columns[j][num-1] = true;
                    tables[table][num-1] = true;
                    board[i][j] = (char)('0'+num);
                    if(j==8)
                        //下一行
                        dfs(i+1,0);
                    else
                        //下一列
                        dfs(i,j+1);
                    //这里可能是当前位置不能选取这个数,因为选取完这个数之后下一个位置的数无法找到合适的数
                    //也可能是当前的i和j下一个位置已经到达终点,然后return,就会走到这里
                    if(!find){
                    rows[i][num-1] = false;
                    columns[j][num-1] = false;
                    tables[table][num-1] = false;
                    board[i][j] = '.';
                    }else{
                        //如果找到了所有的值,dfs(9,0)就会将find置为true,然后返回dfs(8,8)的if(!find)这里,之后就会继续返回,直到返回dfs(0,0)的这里
                        return ;
                    }
                }
                }      
        }
    }
    

    python的AC

    class Solution:
    
    def solveSudoku(self, board: List[List[str]]) -> None:
        #对各行各列各块的元素进行归类
        self.row = [set() for i in range(9)]
        self.col = [set() for i in range(9)]
        self.box = [set() for i in range(9)]
        #记录固定元素的位置
        self.pos_Occup = set()
    
        for i in range(9):
            for j in range(9):
                m = board[i][j]
                if m.isdigit():
                    box_index = (i//3)*3 + j//3
                    self.row[i].add(m)
                    self.col[j].add(m)
                    self.box[box_index].add(m)
                    self.pos_Occup.add(i*9+j)
    
        self.traceBack(board,0)
    def traceBack(self,board,index):
        if index>= 81:
            return True
        #如果是事先已固定的元素,则跳过并判断下一个元素
        if index in self.pos_Occup:
            return self.traceBack(board,index+1)
        i,j = index//9,index%9
        box_index = (i//3)*3 + j//3
        for m in ['1','2','3','4','5','6','7','8','9']:
            if (m not in self.row[i]) and (m not in self.col[j]) and (m not in self.box[box_index]):
                self.row[i].add(m)
                self.col[j].add(m)
                self.box[box_index].add(m)
                board[i][j] = m
                #如果下一步无法进行下去,删除当前元素并进行下次尝试
                if not self.traceBack(board,index+1):
                    self.row[i].remove(m)
                    self.col[j].remove(m)
                    self.box[box_index].remove(m)
                    board[i][j] = '.'
                else:
                    return True
        #从1-9所有尝试失败,回退
        return False
    
    欢迎查阅
  • 相关阅读:
    JAVA SkipList 跳表 的原理和使用例子
    TreeMap、HashMap、ConcurrentSkipListMap之性能比较
    CompletionService 和ExecutorService的区别和用法
    1. java.util.concurrent
    JAVA Concurrent包 中的并发集合类
    并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
    Objective-C中 ==、isEqual、isEqualToString判断字符串相等
    设置UIButton的文字显示位置、字体的大小、字体的颜色
    9个完整android开源app项目
    android 开源项目集合
  • 原文地址:https://www.cnblogs.com/gh110/p/12158173.html
Copyright © 2020-2023  润新知