<span>蓝桥杯训练3</span>
煤球数目
- 有一堆煤球,堆成三角棱锥形。具体: 第一层放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