newkid在itpub发表了最大子集问题的等价问题PL/SQL程序。
create or replace function f_set(n in number) return number
as
function f2(ball in number,box in number) return number
as
v_ret number;
begin
if ball=0 or box=1 then
return 1;
end if;
v_ret :=0;
for i in 0..ball loop ------ 第一个盒子可以放0个到N个球
v_ret:=v_ret+f2(i,box-1);
end loop;
return v_ret;
end;
begin
return f2(n-1,n);
end;
/
我让DeepSeek将上述PL/SQL翻译成Python,并告知格点集合问题相当于从(1,N)走到(N,1),只允许向下或者向右,总共几种走法?
又等价于把N-1个球放到N个盒子,有几种方法?改写上述python程序,使之不但输出路径条数,还输出具体路径。
输出代码如下:
def f_set_with_paths(n):
def f2(ball, box):
if ball == 0 or box == 1:
# 返回路径数量和解的列表
if ball == 0:
# 所有球都在最后一个盒子
return 1, [[0] * (box - 1) + [ball]]
else: # box == 1
# 所有球都在第一个盒子
return 1, [[ball]]
total_paths = 0
all_solutions = []
for i in range(0, ball + 1): # 第一个盒子可以放0个到ball个球
paths, solutions = f2(i, box - 1)
total_paths += paths
# 在每个解的前面加上当前盒子放的数量
for sol in solutions:
all_solutions.append([ball - i] + sol)
return total_paths, all_solutions
paths_count, solutions = f2(n - 1, n)
# 将盒子分配方案转换为格点路径
grid_paths = []
for sol in solutions:
path = [(1, n)] # 起点 (1, N)
x, y = 1, n
# 每个盒子的球数表示向右走的步数
for i in range(len(sol)):
# 向右走 sol[i] 步
for step in range(sol[i]):
x += 1
path.append((x, y))
# 向下走1步(除了最后一个)
if i < len(sol) - 1:
y -= 1
path.append((x, y))
grid_paths.append(path)
return paths_count, solutions, grid_paths
# 测试
if __name__ == "__main__":
n = 5
paths_count, box_solutions, grid_paths = f_set_with_paths(n)
print(f"路径条数: {paths_count}")
print(f"\n盒子分配方案 (每个盒子放的球数):")
for i, sol in enumerate(box_solutions, 1):
print(f"方案 {i}: {sol}")
print(f"\n格点路径 (从(1,{n})到({n},1)):")
for i, path in enumerate(grid_paths, 1):
print(f"路径 {i}: {path}")
这个改写后的程序:
- 保持原有逻辑:仍然计算从(1,N)到(N,1)只允许向下或向右的路径数
- 输出路径条数:返回总的路径数量
- 输出具体路径:
- 盒子分配方案:显示每个盒子放的球数(向右走的步数)
- 格点路径:显示从(1,N)到(N,1)的具体格点路径
算法解释:
- 把N-1个球放到N个盒子 ↔ 从(1,N)走到(N,1)
- 每个盒子放的球数 = 在该行向右走的步数
- 换到下一行 = 向下走一步
- 边界条件:球数为0或盒子数为1时只有一种分配方式
示例输出:
对于n=3,会输出所有从(1,3)到(3,1)的路径,如:
- (1,3)→(2,3)→(3,3)→(3,2)→(3,1)
- (1,3)→(1,2)→(2,2)→(3,2)→(3,1) 等
当n=5时,运行结果如下
time python3 pyboxpath.py
路径条数: 70
盒子分配方案 (每个盒子放的球数):
方案 1: [4, 0, 0, 0, 0]
...
方案 70: [0, 0, 0, 0, 4]
格点路径 (从(1,5)到(5,1)):
路径 1: [(1, 5), (2, 5), (3, 5), (4, 5), (5, 5), (5, 4), (5, 3), (5, 2), (5, 1)]
...
路径 70: [(1, 5), (1, 4), (1, 3), (1, 2), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1)]
real 0m0.081s
user 0m0.016s
sys 0m0.008s
再去掉具体路径输出,分别对n=8、9、12、15计时
import time
def f_set(n):
def f2(ball, box):
if ball == 0 or box == 1:
return 1
v_ret = 0
for i in range(0, ball + 1):
v_ret += f2(i, box - 1)
return v_ret
return f2(n - 1, n)
def main():
# 测试不同的n值
n_values = [8,9,12,15]
results = []
for n in n_values:
start_time = time.time()
paths_count = f_set(n)
end_time = time.time()
execution_time = end_time - start_time
results.append({
'n': n,
'paths_count': paths_count,
'execution_time': execution_time
})
# 输出结果
print("n\t路径条数\t用时(秒)")
print("-" * 30)
for result in results:
print(f"{result['n']}\t{result['paths_count']}\t\t{result['execution_time']:.6f}")
if __name__ == "__main__":
main()
执行结果
python3 pybox.py
n 路径条数 用时(秒)
------------------------------
8 3432 0.000812
9 12870 0.003067
12 705432 0.164429
15 40116600 9.409100

483

被折叠的 条评论
为什么被折叠?



