Initial
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
.venvs
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
|
# 已忽略包含查询文件的默认文件夹
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
Generated
BIN
Binary file not shown.
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="com.wenjun.codeepiphany.luogu.settings">
|
||||||
|
<option name="queryCriteria">
|
||||||
|
<map>
|
||||||
|
<entry key="LuoGuChallengesView-latestUI" value="QueryParameters" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState">
|
||||||
|
<option name="chatAppRouterInfo" value="chat-session" />
|
||||||
|
<option name="progress" value="1.0" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+5
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<option name="SOFT_MARGINS" value="80" />
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
||||||
Generated
+5
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="默认_mod" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module external.system.id="pyproject.toml" type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="uv (exercises)" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.14 (exercises)" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+9
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/exercises.iml" filepath="$PROJECT_DIR$/.idea/exercises.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/exercises@1.iml" filepath="$PROJECT_DIR$/.idea/exercises@1.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PyProjectModelSettings">
|
||||||
|
<option name="showConfigurationNotification" value="false" />
|
||||||
|
<option name="usePyprojectToml" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
import sys
|
||||||
|
from typing import Iterable, Iterator, TYPE_CHECKING
|
||||||
|
|
||||||
|
|
||||||
|
class State(int):
|
||||||
|
def get_digit(self, idx): # 0 开始
|
||||||
|
return self // (10 ** idx) % 10
|
||||||
|
|
||||||
|
def with_digit(self, idx: int, val: int) -> "State":
|
||||||
|
return State(self + (val - self.get_digit(idx)) * 10 ** idx)
|
||||||
|
|
||||||
|
def get_coord_digit(self, row: int, col: int):
|
||||||
|
idx = 3 * (3 - row) - (col + 1)
|
||||||
|
return self.get_digit(idx)
|
||||||
|
|
||||||
|
def with_coord_digit(self, row: int, col: int, val: int) -> "State":
|
||||||
|
idx = 3 * (3 - row) - (col + 1)
|
||||||
|
return self.with_digit(idx, val)
|
||||||
|
|
||||||
|
def get_number_coord(self, n: int = 0) -> tuple[int, int]:
|
||||||
|
for r in range(3):
|
||||||
|
for c in range(3):
|
||||||
|
if self.get_coord_digit(r, c) == n:
|
||||||
|
return r, c
|
||||||
|
raise ValueError(f"No {n} in state {self}")
|
||||||
|
|
||||||
|
def get_possible_steps(self) -> Iterable["State"]:
|
||||||
|
x0, y0 = self.get_number_coord()
|
||||||
|
if x0 > 0:
|
||||||
|
yield self.with_coord_digit(x0, y0, self.get_coord_digit(x0 - 1, y0)) \
|
||||||
|
.with_coord_digit(x0 - 1, y0, 0)
|
||||||
|
if y0 > 0:
|
||||||
|
yield self.with_coord_digit(x0, y0, self.get_coord_digit(x0, y0 - 1)) \
|
||||||
|
.with_coord_digit(x0, y0 - 1, 0)
|
||||||
|
if x0 < 2:
|
||||||
|
yield self.with_coord_digit(x0, y0, self.get_coord_digit(x0 + 1, y0)) \
|
||||||
|
.with_coord_digit(x0 + 1, y0, 0)
|
||||||
|
if y0 < 2:
|
||||||
|
yield self.with_coord_digit(x0, y0, self.get_coord_digit(x0, y0 + 1)) \
|
||||||
|
.with_coord_digit(x0, y0 + 1, 0)
|
||||||
|
|
||||||
|
def compare_with(self, other_state: "State") -> int:
|
||||||
|
# return 0
|
||||||
|
# return 9 - sum(self.get_digit(idx) == other_state.get_digit(idx) for idx in range(9))
|
||||||
|
# return max(0, 8 - sum(self.get_digit(idx) == other_state.get_digit(idx) for idx in range(9)))
|
||||||
|
d1 = sum(self.get_digit(idx) != other_state.get_digit(idx) for idx in range(9))
|
||||||
|
if self.get_number_coord() != other_state.get_number_coord():
|
||||||
|
d1 -= 1
|
||||||
|
d2 = self.manhattan_distance(other_state)
|
||||||
|
if d1 > d2: print("?????????", self, other_state, d1, d2)
|
||||||
|
return d1
|
||||||
|
|
||||||
|
def manhattan_distance(self, other_state: "State") -> int:
|
||||||
|
number_coords = {}
|
||||||
|
other_number_coords = {}
|
||||||
|
for r in range(3):
|
||||||
|
for c in range(3):
|
||||||
|
number_coords[self.get_coord_digit(r, c)] = (r, c)
|
||||||
|
other_number_coords[other_state.get_coord_digit(r, c)] = (r, c)
|
||||||
|
|
||||||
|
# del number_coords[0]
|
||||||
|
# del other_number_coords[0]
|
||||||
|
return sum(
|
||||||
|
abs(number_coords[i][0] - other_number_coords[i][0]) + abs(number_coords[i][1] - other_number_coords[i][1])
|
||||||
|
for i in range(1, 9))
|
||||||
|
|
||||||
|
|
||||||
|
class StateNode:
|
||||||
|
def __init__(self,
|
||||||
|
state: State | int | str, cost: int,
|
||||||
|
heuristic_cost: int,
|
||||||
|
previous_state: State | None = None):
|
||||||
|
self.state = State(state)
|
||||||
|
self.cost = cost # g
|
||||||
|
self.heuristic_cost = heuristic_cost # h
|
||||||
|
self.previous_state = previous_state
|
||||||
|
self.running_iterator: Iterator[State] | None = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def evaluated_cost(self):
|
||||||
|
return self.heuristic_cost + self.cost
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
return self.evaluated_cost < other.evaluated_cost
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"{self.state} (g={self.cost}, h={self.heuristic_cost})"
|
||||||
|
|
||||||
|
|
||||||
|
def dfs_solve(original_state: State, final_state: State, max_cost: int = 2) -> int | bool:
|
||||||
|
open_list: list[StateNode] = [StateNode(original_state, 0, original_state.compare_with(final_state))]
|
||||||
|
next_max_cost: int | float = float("inf")
|
||||||
|
while open_list:
|
||||||
|
current_node = open_list[-1]
|
||||||
|
print(open_list, file=sys.stderr)
|
||||||
|
if current_node.state == final_state:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if current_node.running_iterator is None:
|
||||||
|
current_node.running_iterator = iter(current_node.state.get_possible_steps())
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
new_state = next(current_node.running_iterator)
|
||||||
|
if new_state == current_node.previous_state:
|
||||||
|
continue
|
||||||
|
new_node = StateNode(new_state, current_node.cost + 1, new_state.compare_with(final_state),
|
||||||
|
current_node.state)
|
||||||
|
if new_node.evaluated_cost > max_cost:
|
||||||
|
next_max_cost = min(new_node.evaluated_cost, next_max_cost)
|
||||||
|
continue
|
||||||
|
open_list.append(new_node)
|
||||||
|
except StopIteration:
|
||||||
|
open_list.pop()
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
return int(next_max_cost)
|
||||||
|
else:
|
||||||
|
return next_max_cost
|
||||||
|
|
||||||
|
|
||||||
|
def ida_star_solve(original_state: State, final_state: State) -> int:
|
||||||
|
max_cost = original_state.compare_with(final_state)
|
||||||
|
while True:
|
||||||
|
print(max_cost, "!!!!!!", file=sys.stderr)
|
||||||
|
result = dfs_solve(original_state, final_state, max_cost)
|
||||||
|
if result is True:
|
||||||
|
return max_cost
|
||||||
|
max_cost = result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
original_state = State(input())
|
||||||
|
final_state = State(123804765)
|
||||||
|
print(ida_star_solve(original_state, final_state))
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import heapq
|
||||||
|
import sys
|
||||||
|
|
||||||
|
INT_INF = 0x7fffffff
|
||||||
|
|
||||||
|
|
||||||
|
class GraphMatrix:
|
||||||
|
def __init__(self, size: int):
|
||||||
|
self.vertices = size
|
||||||
|
self.matrix = [[[] for _ in range(size)] for _ in range(size)]
|
||||||
|
|
||||||
|
def add_edge(self, start: int, end: int, weight: int = 1):
|
||||||
|
self.matrix[start][end].append(weight)
|
||||||
|
|
||||||
|
def get_edge(self, start: int, end: int, invert: bool = False) -> list[int]:
|
||||||
|
if invert:
|
||||||
|
return self.matrix[end][start]
|
||||||
|
else:
|
||||||
|
return self.matrix[start][end]
|
||||||
|
|
||||||
|
def get_edge_min(self, start: int, end: int, invert: bool = False) -> int:
|
||||||
|
return min(self.get_edge(start, end, invert))
|
||||||
|
|
||||||
|
def get_adjacent_vertices(self, vertex: int, invert: bool = False) -> list[int]:
|
||||||
|
return [i for i in range(self.vertices) if self.get_edge(vertex, i, invert)]
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "\n".join([" | ".join(map(str, row)) for row in self.matrix])
|
||||||
|
|
||||||
|
|
||||||
|
class VertexNode:
|
||||||
|
def __init__(self, vertex: int, cost: int, heuristic_cost: int = 0):
|
||||||
|
self.vertex = vertex
|
||||||
|
self.cost = cost
|
||||||
|
self.heuristic_cost = heuristic_cost
|
||||||
|
|
||||||
|
@property
|
||||||
|
def evaluated_cost(self):
|
||||||
|
return self.heuristic_cost + self.cost
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
return self.evaluated_cost < other.evaluated_cost
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"#{self.vertex}(g={self.cost},h={self.heuristic_cost})"
|
||||||
|
|
||||||
|
|
||||||
|
def dijkstra_init(graph: GraphMatrix, end: int) -> dict[int, int]:
|
||||||
|
open_list: list[VertexNode] = []
|
||||||
|
heuristic_map: dict[int, int] = {}
|
||||||
|
visited: set[int] = set()
|
||||||
|
|
||||||
|
heuristic_map[end] = 0
|
||||||
|
heapq.heappush(open_list, VertexNode(end, 0))
|
||||||
|
while open_list:
|
||||||
|
current_node = heapq.heappop(open_list)
|
||||||
|
if current_node.vertex in visited:
|
||||||
|
continue
|
||||||
|
visited.add(current_node.vertex)
|
||||||
|
|
||||||
|
for next_vertex in graph.get_adjacent_vertices(current_node.vertex, True):
|
||||||
|
if next_vertex in visited:
|
||||||
|
continue
|
||||||
|
new_cost = current_node.cost + graph.get_edge_min(current_node.vertex, next_vertex, True)
|
||||||
|
# 如果新路径更短,或者该节点第一次被访问
|
||||||
|
if new_cost < heuristic_map.get(next_vertex, INT_INF):
|
||||||
|
heuristic_map[next_vertex] = new_cost
|
||||||
|
heapq.heappush(open_list, VertexNode(next_vertex, new_cost))
|
||||||
|
|
||||||
|
return heuristic_map
|
||||||
|
|
||||||
|
def a_star_solve(graph: GraphMatrix,
|
||||||
|
start: int, end: int,
|
||||||
|
count: int,
|
||||||
|
heuristic_map: dict[int, int]) -> list[int]:
|
||||||
|
open_list: list[VertexNode] = []
|
||||||
|
# 此处不是「visited_record」!我们要记录所有访问,只是不需要展开过多。
|
||||||
|
# 因此也不需要「更新 g 值,因为我们记录了一切 g 的节点!
|
||||||
|
# 逻辑是:1. 每条最短路径上的每个节点一定是被 expand 过的;2. 可采用的 h 可保证先找更短路
|
||||||
|
expanded_record: dict[int, int] = {}
|
||||||
|
# node_record: dict[int, VertexNode] = {}
|
||||||
|
original_node = VertexNode(start, 0, heuristic_map.get(start, INT_INF))
|
||||||
|
heapq.heappush(open_list, original_node)
|
||||||
|
# node_record[start] = original_node
|
||||||
|
result_list: list[int] = []
|
||||||
|
|
||||||
|
while open_list:
|
||||||
|
# print(open_list, file=sys.stderr)
|
||||||
|
current_node = heapq.heappop(open_list)
|
||||||
|
expanded_record[current_node.vertex] = expanded_record.get(current_node.vertex, 0) + 1
|
||||||
|
# print(current_node, open_list, file=sys.stderr)
|
||||||
|
if current_node.vertex == end:
|
||||||
|
result_list.append(current_node.cost)
|
||||||
|
if len(result_list) >= count:
|
||||||
|
return result_list
|
||||||
|
|
||||||
|
if expanded_record.get(current_node.vertex, 0) > count:
|
||||||
|
continue # 不扩展,剪枝
|
||||||
|
|
||||||
|
for next_vertex in graph.get_adjacent_vertices(current_node.vertex):
|
||||||
|
for edge_weight in graph.get_edge(current_node.vertex, next_vertex):
|
||||||
|
next_node = VertexNode(
|
||||||
|
next_vertex,
|
||||||
|
current_node.cost + edge_weight,
|
||||||
|
heuristic_map.get(next_vertex, INT_INF)
|
||||||
|
)
|
||||||
|
heapq.heappush(open_list, next_node)
|
||||||
|
|
||||||
|
return result_list
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
vertices_count, edge_count, result_count = map(int, input().split())
|
||||||
|
graph = GraphMatrix(vertices_count + 1)
|
||||||
|
for _ in range(edge_count):
|
||||||
|
start, end, weight = map(int, input().split())
|
||||||
|
graph.add_edge(start, end, weight)
|
||||||
|
# print(graph, file=sys.stderr)
|
||||||
|
heuristic_map = dijkstra_init(graph, 1)
|
||||||
|
print(heuristic_map, file=sys.stderr)
|
||||||
|
result_list = a_star_solve(graph, vertices_count, 1, result_count, heuristic_map)
|
||||||
|
# print(result_list, file=sys.stderr)
|
||||||
|
result_list += [-1] * (result_count - len(result_list))
|
||||||
|
print(*result_list, sep="\n")
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import itertools
|
||||||
|
import sys
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
ROW_COUNT = 341_799
|
||||||
|
MOD = 998_244_353
|
||||||
|
|
||||||
|
PatternCharType = Literal[0, 1]
|
||||||
|
|
||||||
|
|
||||||
|
def get_pattern_multiplier(pattern: tuple[PatternCharType, PatternCharType, PatternCharType]) -> int:
|
||||||
|
match pattern:
|
||||||
|
case (0, 0, 0) | (0, 0, 1) | (1, 0, 0) | (0, 1, 0) | (1, 0, 1): return 21 * 21
|
||||||
|
case (0, 1, 1) | (1, 1, 0): return 21 * 26
|
||||||
|
case (1, 1, 1): return 26 * 26
|
||||||
|
case _: raise ValueError(f"Unknown pattern: {pattern}")
|
||||||
|
|
||||||
|
|
||||||
|
dp: dict[PatternCharType, list[tuple[int, int]]] = {0: [(-1, -1), (5, 0)], 1: [(-1, -1), (0, 21)]}
|
||||||
|
|
||||||
|
for _ in range(ROW_COUNT - 1):
|
||||||
|
for c in 0, 1:
|
||||||
|
dp[c].append((dp[c][-1][1] * 5 % MOD, (dp[c][-1][0] + dp[c][-1][1]) * 21 % MOD))
|
||||||
|
|
||||||
|
answer = 0
|
||||||
|
|
||||||
|
for pattern1 in itertools.product([0, 1], repeat=3):
|
||||||
|
for pattern2 in itertools.product([0, 1], repeat=3):
|
||||||
|
# noinspection PyTypeChecker
|
||||||
|
answer += dp[pattern1[0]][ROW_COUNT][pattern2[0]] \
|
||||||
|
* dp[pattern1[1]][ROW_COUNT][pattern2[1]] \
|
||||||
|
* dp[pattern1[2]][ROW_COUNT][pattern2[2]] \
|
||||||
|
* get_pattern_multiplier(pattern1) \
|
||||||
|
* get_pattern_multiplier(pattern2) \
|
||||||
|
% MOD
|
||||||
|
|
||||||
|
print(dp[0][:100], dp[1][:100], file=sys.stderr, sep="\n")
|
||||||
|
print(answer % MOD)
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
perl_amount, color_kind_amount = map(int, input().split())
|
||||||
|
color_counts: list[tuple[int, int]] = []
|
||||||
|
for i in range(color_kind_amount):
|
||||||
|
color_counts.append((i, int(input())))
|
||||||
|
|
||||||
|
color_counts.sort(key=lambda x: x[1])
|
||||||
|
|
||||||
|
colors: list[int] = []
|
||||||
|
for i, color_count in color_counts:
|
||||||
|
colors += [i + 1] * color_count
|
||||||
|
print(colors, file=sys.stderr)
|
||||||
|
for i in range(perl_amount // 2):
|
||||||
|
print(colors[i], colors[i + perl_amount // 2])
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[project]
|
||||||
|
name = "exercises"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.11"
|
||||||
|
dependencies = []
|
||||||
Reference in New Issue
Block a user