d这套题,偏向模拟、最后一题可以用BFS或者DP解,整体难度不大。
一、夹吃棋
题目描述
在一个 3 * 3 的棋盘上,小红和小紫正在玩“夹吃棋”。 所谓“夹吃棋”,即如果存在一个白子,它的两侧 (横向或者纵向)相邻都是黑子,则这个棋子将被“夹吃”,对于黑棋亦然。
如果一个棋盘的局面没有一方被夹吃,或者黑白双方都被对面夹吃,则认为是平局。如果只有一方夹吃了另一方,则认为夹吃方赢,被夹吃方输。
小红执黑棋,小紫执白棋,现在给定一个局面,请你判断当前棋局是谁获胜。
输入描述
第一行输入一个正整数 t (1 <= t <= 10000),代表询问的次数。
接下来每组询问输入三行,,每行是一个长度为3的字符串,字符串仅由'o','.','*'组成。
其中 o 代表白棋,* 代表黑棋,. 代表未放置棋子。
输出描述
小红获胜输出“kou”,小紫获胜输出“yukan”,平局输出“draw”。
输入示例
3
...
o*o
...
o**
ooo
..*
o*o
*o*
o*o
输出示例
yukan
kou
draw
题目分析:
【题目类型:纯模拟,遍历,枚举】
夹吃只有横纵两种情况,3*3的棋盘,横有3种,纵有3种,每种情况又分为黑夹白和白夹黑2种。所以一共就12种情况。遍历所有情况,记录黑夹白和白夹黑出现的次数,然后根据题意输出即可。
代码:
def calc(matrix):
yukan = 0
kou = 0
# 横向
for i in range(3):
if matrix[i][0] == matrix[i][2] and matrix[i][2] == 'o' and matrix[i][1] == '*':
yukan += 1
elif matrix[i][0] == matrix[i][2] and matrix[i][2] == '*' and matrix[i][1] == 'o':
kou += 1
# 纵向
for i in range(3):
if matrix[0][i] == matrix[2][i] and matrix[2][i] == 'o' and matrix[1][i] == '*':
yukan += 1
elif matrix[0][i] == matrix[2][i] and matrix[2][i] == '*' and matrix[1][i] == 'o':
kou += 1
if (yukan > 0 and kou > 0) or (yukan == 0 and kou == 0):
return "draw"
elif yukan > 0:
return "yukan"
return "kou"
n = int(input())
for _ in range(n):
matrix = []
for i in range(3):
temp_in = input().split()[0]
matrix.append([temp_in[0], temp_in[1], temp_in[2]])
print(calc(matrix))
二、小红买药
题目描述
小红准备买药治病。已知共有 n 种症状和 m 种药,第 i 种药可以治疗一些症状,但可能会导致一些副作用,添加一些新的症状。小红依次服用了一些药,请你告诉小红,当她每次服用一副药时,当前还有多少症状?
输入描述
第一行输入一个正整数 n(1 <= n <= 20),代表症状的数量
第二行输入一个长应为 n 的 01 串,第 i 位是 "1" 代表小红目前有第 i 个症状,第i位是 "0" 代表没有该症状。
第三行输入一个正整数 m( 1<= m <= 10^4),代表药的数量。
接下来的 2 * m 行,每 2 行描述一副药:
第一行输入一个长度为 n 的 01 串,代表该药能治疗的症状。’1‘代表可以治疗,‘0’代表不能治疗。
第二行输入一个长度为 n 的 01 串,代表该药会产生的副作用。’1‘代表会产生该症状,’0‘代表不会产生。
接下来的一行,输入一个正整数 q( 1<= q <= 10^4),代表小红服用的药数量。
接下来的 q 行,每行输入一个正整数 u(1 <= ai, u <= m),代表小红服用了第 u 副药。
保证每副药的副作用产生的症状和该药治疗的症状是不会重复的,即不会存在同一个位置的两个 01 串都是‘1’。
输出描述
输出 q 行,每行输入一个正整数,代表当前小红服用药后,身体有多少症状。
输入示例
4
0101
3
1100
0010
0101
1000
1001
0000
3
2
3
1
输出示例
1
0
1
题目分析:
【题目类型:模拟】
没什么算法,理解题意按照描述编写程序即可
代码:
n = int(input())
current_state = [int(i) for i in input()]
m = int(input())
drug_list = []
for _ in range(m):
drug_list.append([[int(i) for i in input()], [int(i) for i in input()]])
def cure(state, drug):
for idx in range(len(state)):
if state[idx] and drug[idx]:
state[idx] = 0
return state
def effect(state, drug):
cnt = 0
for idx in range(len(state)):
if drug[idx] == 1 and state[idx] == 0:
state[idx] = 1
if state[idx]:
cnt += 1
return state, cnt
q = int(input())
for _ in range(q):
idx = int(input()) - 1
current_state = cure(current_state, drug_list[idx][0])
current_state, ans = effect(current_state, drug_list[idx][1])
print(ans)
三、皇后移动的最小步数
题目描述
有一个 n 行 m 列的棋盘,有一些格子是障碍物不能通过。
小红控制一个皇后在从左上角出发,每次移动她可以控制皇后进行以下三种方式中的一种:
1.向右移动若干个格子。
2.向下移动若干个格子。
3.向右下移动若干个格子。
用数学语言描述,当前的坐标在 (x, y) 时,每次移动可以到 (x + k, y) 或 (x, y + k) 或 (x + k, y + k) 其中 k 为任意正整数。移动的前提是,路径上没有障碍物。 小红想知道,皇后从左上角移动到右下角,最少要移动多少步?
输入描述
第一行输入两个正整数 n 和 m(1 <= n,m <= 2000),代表行数和列数。
接下来的 n 行,每行输入一个长度 m 的字符串,用来表示棋盘。
其中 "." 代表可以通过的位置,"*" 代表障碍物。 保证左上角和右下角都不是障碍物。
输出描述
如果无法到达,请输出-1。
否则输出一个整数,代表最少的移动次数。
输入示例
4 5
...*.
*..**
.....
.....
输出示例
2
题目分析:
【题目类型:动态规划、BFS】
动态规划的思想,是用dp[i][j][w]保存最后一步用方式w,到达i, j的最小步数,后面的位置可以根据前面的位置的步数求得。
BFS的思想,是从1,1点出发,第n次BFS到达终点处,那么就是最少的步数。
同样的思想,其他语言的代码可以跑通。但是python最后几个n和m为2000用例总是跑不过,不太清楚是为什么,可能是python的问题。
代码:
# BFS
n, m = map(int, input().split())
grid = [input() for _ in range(n)] # 输入地图的每一行
visited = [[ False for _ in range(m)] for __ in range(n)]
ways = [[1, 0], [0, 1], [1, 1]]
def bfs(grid, n, m):
if grid[n-1][m-1] == "*":
return -1
if n == 1 and m == 1:
return 0
queue = [[0,0]]
visited[0][0] = True
step = 0
while len(queue) > 0:
step += 1
next_queue = []
for xy in queue:
for w in ways:
next_x = xy[0] + w[0]
next_y = xy[1] + w[1]
while next_x < n and next_y < m and grid[next_x][next_y] == ".":
if not visited[next_x][next_y]:
if next_x == n-1 and next_y == m-1:
return step
visited[next_x][next_y] = True
next_queue.append([next_x, next_y])
next_x += w[0]
next_y += w[1]
queue = next_queue
return -1
print(bfs(grid, n, m))
# 动态规划
n, m = map(int, input().split())
grid = [list(input()) for _ in range(n)] # 输入地图的每一行
dp = [[[10000000, 10000000, 10000000] for _ in range(m)] for __ in range(n)] # n*m <= 4000000, [-1, -1, -1] 分别表示按照向右、向下、向右下的方式来到的步数
dp[0][0] = [1, 1, 1]
for i in range(n):
for j in range(m):
if grid[i][j] == "*" or i+j == 0:
continue
dp[i][j][0] = min(dp[i][j-1][0], min(dp[i][j-1])+1)
dp[i][j][1] = min(dp[i-1][j][1], min(dp[i-1][j])+1)
dp[i][j][2] = min(dp[i-1][j-1][2], min(dp[i-1][j-1])+1)
ans = min(dp[n-1][m-1])
if ans >= 10000000:
ans = -1
print(ans)