- 2017年省赛-填空题-方格分割-644
'''切割线一定会经过图的中心点,只要确定半条到达
边界的分割线,就能根据这半条对称画出另外半条'''
count = 0
book = [[0]*7 for i in range(7)] #多给一个
next_node = [[-1, 0], [1, 0], [0, -1], [0, 1]]
#按什么顺序应该无所谓吧,也没说字典序啥的
def dfs(x, y):
global count #全局变量
if x == 0 or y == 0 or x == 6 or y == 6:
# 走到边了,完成分割
count += 1
return
book[x][y], book[6-x][6-y] = 1, 1
# 对当前点和当前点的对称点都标记访问
for i in range(4):
# 新坐标
tx = x + next_node[i][0]
ty = y + next_node[i][1]
# 如果出界
if tx < 0 or tx > 6 or ty < 0 or ty > 6:
continue
# 没走过,继续往下走
if book[tx][ty] == 0:
dfs(tx, ty)
book[x][y], book[6-x][6-y] = 0, 0
# 一次dfs结束,取消这个点及其对称点的标记
dfs(3,3) # 中心点(3, 3),从(3, 3)出发
print(count//4)
- 2017年省赛-填空题-迷宫-641
''' 直接一个一个数也很快。画出通路,通路上的房间都可以出去。'''
maze = ['UDDLUULRUL', 'UURLLLRRRU',
'RRUURLDLRD', 'RUDDDDUUUU',
'URUDLLRRUU', 'DURLRLDLRL',
'ULLURLLRDU', 'RDLULLRDDD',
'UUDDUDUDLL', 'ULRDLUURRR']
book = [[0]*11 for _ in range(11)]
count = 0
def dfs(x, y):
global count
# 走出去了
if x < 0 or x > 9 or y < 0 or y > 9:
count += 1
return
# 已经走过了
if book[x][y] == 1:
return
# 对当前点标记访问
book[x][y] = 1
if maze[x][y] == 'L':
dfs(x, y-1)
if maze[x][y] == 'R':
dfs(x, y+1)
if maze[x][y] == 'U':
dfs(x-1, y)
if maze[x][y] == 'D':
dfs(x+1, y)
book[x][y] = 0
# 一次dfs结束,取消对当前点的标记
# 对每一个房间(每一个点)进行dfs
for i in range(10):
for j in range(10):
dfs(i, j)
print(count)
- 2017年省赛-正则问题-106
'''
((xx|xxx)x|(x|xx))xx
或的两边保留最长的一个x串
每一次dfs()只算一个()内的长度,ans是一个()内x的长度
temp表示从(到|的长度或一整个()内的x长度
'''
s = input()
pos = 0 # 当前位置
def dfs():
global pos
temp, ans = 0, 0
while pos < len(s):
if s[pos] == '(':
pos += 1
temp += dfs()
elif s[pos] == 'x':
pos += 1
temp += 1
elif s[pos] == '|':
pos += 1
ans = max(ans, temp)
temp = 0
elif s[pos] == ')':
pos += 1
ans = max(ans, temp)
return ans
ans = max(ans, temp)
return ans
print(dfs())
- 2016年省赛-填空题-寒假作业-1388
剪枝,不用生成一个完整的排列。需要自写全排列。
ans = 0
l = [0 for _ in range(15)]
# 用来存放每一次的13个数,l[0]空置
book = [0 for _ in range(15)]
def check3():
# 检查前三个数是否符合等式
return l[1] + l[2] == l[3]
def check6():
return l[4] - l[5] == l[6]
def check9():
return l[7] * l[8] == l[9]
def check12():
return l[10] / l[11] == l[12]
def dfs(num):
global ans
if num == 13:
if check12():
ans += 1
return
if num == 4 and not check3():
return
if num == 7 and not check6():
return
if num == 10 and not check9():
return
for i in range(1, 14):
if book[i] == 0: # 未被访问
l[num] = i
book[i] = 1 # 标记访问
dfs(num+1)
book[i] = 0
dfs(1) # 从第一个方块开始
print(ans)
类似的题目:方格填数-664,但是这一题用dfs也很烦,还不如用全排列暴力求解。
- 2018年省赛-全球变暖-178
这一题也可以用bfs做
还是有一个测试用例不能通过😢
import sys
sys.setrecursionlimit(int(1e4))
N = int(input())
ph = []
for i in range(N):
ph.append(input())
assert len(ph[-1]) == N
book = [[0]*N for _ in range(N)]
next_node = [[-1, 0], [1, 0], [0, 1], [0, -1]]
count = 0
def dfs(x, y):
global flag
book[x][y] = 1
if ph[x+1][y] == '#' and ph[x-1][y] == '#' and ph[x][y+1] == '#' and ph[x][y-1] == '#':
flag = 1
for i in range(4):
tx = x + next_node[i][0]
ty = y + next_node[i][1]
# 把周围所有#都标记上flag
if book[tx][ty] == 0 and ph[tx][ty] == '#':
dfs(tx, ty)
for i in range(N):
for j in range(N):
if ph[i][j] == '#' and book[i][j] == 0: #对符合这个条件的所有点dfs
flag = 0
dfs(i, j)
if flag == 0:
count += 1
print(count)
- 2015年国赛-填空题-四阶幻方-689
和寒假作业简直一模一样。需要不断地剪枝,剪枝,剪枝。
每行每列每条对角线之和应当是34.
(1+16+8+9 = 2+15+8+9 = … = 34)
ans = 0
l = [0 for _ in range(17)]
l[1] = 1
book = [0 for _ in range(17)]
book[1] = 1
def check4():
return 1 + l[2] + l[3] + l[4] == 34
def check8():
return l[5] + l[6] + l[7] + l[8] == 34
def check12():
return l[9] + l[10] + l[11] + l[12] == 34
def check13():
return 1 + l[5] + l[9] + l[13] == 34 and l[4] + l[7] + l[10] + l[13] == 34
def check14():
return l[2] + l[6] + l[10] + l[14] == 34
def check15():
return l[3] + l[7] + l[11] + l[15] == 34
def check16():
return l[13] + l[14] + l[15] + l[16] == 34 and l[4] + l[8] + l[12] + l[16] == 34 and 1 + l[6] + l[11] + l[16] == 34
def dfs(num):
global ans
if num == 17:
if check16():
ans += 1
return
if num == 5 and not check4():
return
if num == 9 and not check8():
return
if num == 13 and not check12():
return
if num == 14 and not check13():
return
if num == 15 and not check14():
return
if num == 16 and not check15():
return
for i in range(2, 17):
if book[i] == 0:
l[num] = i
book[i] = 1
dfs(num+1)
book[i] = 0
dfs(2)
print(ans)
- 2016年省赛-四平方和-122
暴力法:
import math
n = int(input())
# 创建一个平方列表
w = int(math.sqrt(n)) + 1
l = [i ** 2 for i in range(w)]
def fun(m):
for i in range(m):
if n < i ** 2:
continue
for j in range(i, m):
if n < i ** 2 + j ** 2:
continue
for k in range(j, m):
z = n - (i ** 2 + j ** 2 + k ** 2)
if z < 0:
continue
if z in l:
st = sorted([i, j, k, int(math.sqrt(z))])
return st[0], st[1], st[2], st[3]
a, b, c, d = fun(w)
print(a, b, c, d)
dfs代码:
import math
import sys
n = int(input())
l = [0] * 4
def dfs(num, rst, las):
m = int(math.sqrt(rst))
flag = 0
if num > 2:
if m >= las and m ** 2 == rst:
print(l[0], l[1], l[2], m)
sys.exit()
return
for i in range(las, m+1):
l[num] = i
dfs(num+1, rst-i*i, i)
dfs(0, n, 0)
- 2018年省赛-小朋友崇拜圈-182
import sys
#防止无限递归导致 Python 崩溃
sys.setrecursionlimit(int(1e6))
n = int(input())
ls = [0] + list(map(int, input().split()))
book = [0] * (n+1)
ans = 0
def dfs(x, y):
global ans
#终止条件:被访问过
if book[x]:
ans = max(ans, y-book[x]) # 终止值-起始值
return
book[x] = y
dfs(ls[x], y+1)
for i in range(1, n+1):
if not book[i]:
dfs(i, 1)
print(ans)
n, m = map(int, input().split()) # n行m列
mp = []
for i in range(n):
mp.append(list(map(int, input().split())))
assert len(mp) == n
drct = [[1, 0], [-1, 0], [0, 1], [0, -1]] # 出水管在上下左右
book = [[0]*m for _ in range(n)]
flag = 0
s = []
def dfs(x, y, fr):
global flag, s
if x== n-1 and y == m:
flag = 1
for i in range(len(s)):
print("({},{})".format(s[i][0]+1, s[i][1]+1), end=' ')
return
if x < 0 or x >= n or y < 0 or y >= m:
return
if book[x][y] == 1:
return
book[x][y] = 1
# 入栈
s.append([x, y])
# 直管
if mp[x][y] == 5 or mp[x][y] == 6:
dfs(x+drct[fr][0], y+drct[fr][1], fr)
# 弯管
if 1 <= mp[x][y] <= 4:
if fr == 0 or fr == 1: # 进水口在上/下面
dfs(x, y+1, 2)
dfs(x, y-1, 3)
if fr == 2 or fr == 3:
dfs(x+1, y, 0)
dfs(x-1, y, 1)
book[x][y] = 0
s = s[:-1] # 出栈
return
dfs(0, 0, 2)
if flag == 0:
print("impossible")