蓝桥杯训练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
posted @ 2019-12-04 22:21  subeiLY  阅读(184)  评论(0编辑  收藏  举报