码迷,mamicode.com
首页 > 其他好文 > 详细

Sticks

时间:2020-02-25 13:13:27      阅读:74      评论:0      收藏:0      [点我收藏+]

标签:max   cti   href   reverse   word   tab   names   sort   clu   

By cuizhenkai

1.优化搜索顺序

从小到大排序, 优先尝试较长的木棍。

理解:

  • 从最大开始可以较快的排除不可能的分支,避免dfs进入比较深的树。
  • 若从最小开始,则有可能前几根可以拼好,但是后面的不能满足条件,让dfs进入了更深的层。

2. 排除等效冗余

A ) 限制先后加入一根原始木棍的长度递减

理解:

  • 先拼长度为 $x$,再拼为 $y$ 的木棍 $(x < y)$ 与反之是等效的。

B ) 对于当前原始木棒,记录最近一次尝试拼接的长度,如果失败回溯,不再向该木棒中添加一样长的木棍。

—— 这个比较好理解。

C ) 若在当前原始木棒中,尝试的第一根木棍就失败,那么该分支失败。

理解:

  • 按照上面的剪枝,我们可以知道,对一根原始木棒,尝试的第一根木棍就失败,意味着其他的空木棒也必定失败。

D ) 若向一根原始木棒拼接了一根木棍后,恰好成功,但是下面的分支失败,那么此分支失败

理解:

  • 用一根拼好比用若干根其他木棍拼好要更优,原因是长度小的木棍更灵活。

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

大专栏  Stickspan class="meta">#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

int a[105];
int vis[105];
int n = 0;
int len = 0;
int cnt = 0;
int ans;

bool (int s, int now, int last) {
if(s > cnt) {return true;}
if(now == len) {return dfs(s + 1, 0, 1);}
int fail = 0;
for(int i = last; i <= ans; i ++) {
if(!vis[i] && now + a[i] <= len && fail != a[i]) {
vis[i] = 1;
if(dfs(s, now + a[i], i + 1)) {return true;}
fail = a[i];
vis[i] = 0;
if(now == 0 || now + a[i] == len) {return false;}
}
}
return false;
}

int main(int argc, char const *argv[]) {
scanf("%d", &n);
int tot = 0;
int maxm = 0;
for(int i = 1; i <= n; i ++) {
int x;
scanf("%d", &x);
if(x <= 50) {
a[++ans] = x;
tot += a[ans];
maxm = max(maxm, a[ans]);
}
}
sort(a + 1, a + ans + 1);
reverse(a + 1, a + ans + 1);
for(len = maxm; len <= tot; len ++) {
if(tot % len) continue;
cnt = tot / len;
memset(vis, 0, sizeof(vis));
if(dfs(1, 0, 1)) {break;}
}
printf("%d", len);
return 0;
}

实现时的错误:

  • 对于剪枝D的理解不清。

Sticks

标签:max   cti   href   reverse   word   tab   names   sort   clu   

原文地址:https://www.cnblogs.com/lijianming180/p/12360837.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!