Luo2383:狗哥玩木棒 题解

Posted yjzoier

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luo2383:狗哥玩木棒 题解相关的知识,希望对你有一定的参考价值。

Problem

题目背景

狗哥又趁着语文课干些无聊的事了...

题目描述

现给出一些木棒长度,那么狗哥能否用给出的木棒(木棒全用完)组成一个正方形呢?

输入输出格式

输入格式:

输入文件中的第一行是一个整数n表示测试的组数,接下来n行表示每组的测试数据。 每行的第一个数为m(4<=m<=20),接下来m个数ai(1<=ai<=1000)表示木棒的长度。

输出格式:

对于每组测试数据,如果可以组成正方形输出“yes”,否则输出“no”。

输入输出样例

输入样例#1:

3
4 1 1 1 1 
5 10 20 30 40 50 
8 1 7 2 6 4 4 3 5

输出样例#1:

yes
no
yes

Solution

呵呵,这居然是技术分享图片的题目,其实是一道暴搜题,相信大家都会写。

但是,它之所以能被评为技术分享图片是因为纯粹的暴搜是无法过了这题的,需要加一些 剪枝


技术分享图片

这是我的提交记录,可以看到,从一开始的 TLEAC,时间差距是巨大的,甚至同样 AC 的代码也有 5 倍时间的差距。这都是剪枝的操作所导致的。


先来讲讲怎么从 TLEAC,这是我暴搜最初的版本:

bool dfs(int t, int l1, int l2, int l3, int l4){ //t 表示当前到第几个棍子了,l1,l2,l3,l4分别是正方形的四条边的长度,返回值表示是否可行
    if (t == n + 1){return (l1 == l2 && l2 == l3 && l3 == l4);}
    if (dfs(t+1, l1 + a[t], l2, l3, l4)) return true;
    if (dfs(t+1, l1, l2 + a[t], l3, l4)) return true;
    if (dfs(t+1, l1, l2, l3 + a[t], l4)) return true;
    if (dfs(t+1, l1, l2, l3, l4 + a[t])) return true;
    return false;
}

这个暴搜没有经过任何优化,我们需要考虑优化的动机。我们发现,有一些状态是 没有必要枚举下去的,举个例子,如果 (sum = Sigma a_i)(sum) 不是 4 的倍数,那么显然不能拼成正方形;进一步,如果 l1,l2,l3,l4 中的某个数大于 (sum over 4),显然应该返回 false,没有必要枚举下去。

加了这两个优化,代码就 AC 了哈。


还能不能进一步优化呢?
思考刚才那个剪枝,因为剪枝肯定是越早越好,如果我们把棍子按照长度降序排列,那么剪枝的时间肯定会有所提前。这个优化可以把时间优化到原来的 (1 over 5)
至于我的那个 CE,是因为降序排序时 sort(a+1, a+1+n, greater<int>() ) 写成了 sort(a+1, a+1+n, greater<int> ),话说难道我以前都写错了QAQ?

以上是关于Luo2383:狗哥玩木棒 题解的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P2383 狗哥玩木棒

洛谷——P2383 狗哥玩木棒

P2383 狗哥玩木棒

洛谷 P2383 狗哥玩木棒

关于两道搜索的题目

搜索专题练习