POJ1011“木棒”终于解出来了

题目http://acm.pku.edu.cn/JudgeOnline/problem?id=1011

做了两天,一直RE,在网上找了一组又一组的数据,最终发现了异常的地方,47MS通过了。

我的思路是:

设所有子木棍为:S1、S2、S3、、、Sn,且S1>= S2 >= S3 >= … >= Sn

每根拼凑的木棍表示为:Li= {Si1, Si2, Si3… Sim}

定义一个偏序关系:

Li >= Lj 当且仅当

Si1 > Sj1 ||

(Si1 = Sj1 && Si2 > Sj2) ||

(Si1= Sj1 && Si2 = Sj2 && Si3 = Sj3) …

即类似字符串的大小关系。

这样,所有最终拼凑出的木棍能够从大到小排列。

在搜索解的时候,按照从大到小的搜索所有木棍,比如,拼出了第一个木棍,再拼第二根木棍的时候,第二根木棍一定要比第一根木棍小。这样可以避免一些可以避免一些重复搜索。

感谢这组数据,测出了我的bug

45
15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8
15 3 2 11 4 1 8 8 8

while (next == -1 && index.size() > 1) {
    rmvIndex(index, curIndex, sum);
    curIndex = *index.rbegin();
    next = findNextIndex(curIndex);
}
index.size() > 1这句话先开始没有加上,导致了vector类型变量不断pop_back,直到报异常。

一组测试数据如下:

9
15 3 2 11 4 1 8 8 8

6
6 2 2 4 8 8

5
1 1 1 1 1 

2
1 1


4
2 2 9 9

3
1 2 3


64
40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 

40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40 

40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 

40 

7
49 48 47 46 45 44 43

7
3 4 5 5 5 5 13

7
2 7 7 7 7 10 20

6
1 2 3 11 11 20

7
63 2 44 12 60 35 60 


9
5 2 1 5 2 1 5 2 1

4
1 2 3 4

64
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 32
33 31 31 33 

25
13 13 14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 19

19
4 4 4 4 4 4 4 4 4 9 9 9 9 9 9 11 11 11 12

64
40 40 30 35 35 26 15 40 40 40 40 40 40 40 40 40 40 40 40 40 40 


40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40 


40 25 39 46 40 10 4 40 40 37 18 17 16 15 40 40 40 40 40 40 40 


40

45
15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8 15 3 2 11 4 1 8 8 8
15 3 2 11 4 1 8 8 8

0

输出为:

20
10
1
1
11
3
1251
322
20
30
24
276
6
5
64
20
27
454
20

POJ 1011 是“Sticks”问题,主要是将一些长度不一的小木棍拼接成若干根等长的大木棍,求大木棍的最小可能长度。该问题通常使用深度优先搜索(DFS)结合剪枝策略来解决。 由于使用了剪枝策略,其时间复杂度难以精确分析,因为剪枝会减少实际搜索的状态数。在最坏情况下,没有任何剪枝生效,搜索空间为指数级。假设木棍数量为 $n$,木棍长度的上限为 $m$,不剪枝时 DFS 的时间复杂度近似为 $O(2^n)$,因为对于每根木棍都有两种选择:放入当前大木棍或者不放入。 以下是一个简单的 Python 代码示例,实现了该问题的基本思路: ```python def dfs(sticks, target, current_length, start_index, used): if all(used): return True if current_length == target: return dfs(sticks, target, 0, 0, used) last_failed = -1 for i in range(start_index, len(sticks)): if not used[i] and sticks[i] != last_failed and current_length + sticks[i] <= target: used[i] = True if dfs(sticks, target, current_length + sticks[i], i + 1, used): return True used[i] = False last_failed = sticks[i] if current_length == 0 or current_length + sticks[i] == target: return False return False def solve(sticks): total_length = sum(sticks) max_length = max(sticks) sticks.sort(reverse=True) for target in range(max_length, total_length + 1): if total_length % target == 0: used = [False] * len(sticks) if dfs(sticks, target, 0, 0, used): return target sticks = [2, 2, 2, 2] print(solve(sticks)) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值