Sticks 

【题目链接】:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=243

【 随 笔 】:很久之前就遇到这道题,题目意思容易理解,后来自己想到了一个法子,思路也很清晰就将代码敲出来了,用了位运算(后来问师兄是说状态压缩,其实我不知道什么是状态压缩~_~),不过提交的时候超时了,我想着优化代码,尽可能加剪枝的条件,却无从下手,后来搜题解搜到了师兄的博客,题解中剪枝的条件自己能想到的五个中了三个,剩下两个剪枝也容易理解,整个DFS的思路也容易理解,这点值得反思,其中的原因我想是自己先入为主了,在之前的思路上瞎折腾,未果却也不接受考虑另外的可能,其实看了师兄的代码思路后,也就是普普通通的暴力回溯,不多说,先保存TL的代码:

【AC的代码链接】:http://www.cppblog.com/y346491470/articles/155318.html

【超时的代码】

 #include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#define MAXN 500
using namespace std;
int sticks[MAXN];
bool visit[MAXN];
int n, sumlen, res; bool judge(int fac)
{
int i;
for(i=; i<n && visit[i]; ++i);
if(i<n) return false;
else
{
res = fac;
return true;
}
} bool Traverse(int fac)
{
for(int i=; i<(<<n); ++i)
{
int subsum = ;
bool is_useful = true;
for(int k=; k<n; ++k)
{
if(i&(<<k))
{
if(visit[k] || subsum > fac)
{
is_useful = false;
break;
}
else subsum += sticks[k];
}
}
if(is_useful && subsum == fac)
{
for(int k=; k<n; ++k)
{
if(i&(<<k)) visit[k] = true;
}
if(judge(fac) || Traverse(fac)) return true;
for(int k=; k<n; ++k)
{
if(i&(<<k)) visit[k] = false;
}
}
}
return false;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("F:\\test\\input.txt", "r", stdin);
#endif // ONLINE_JUDGE
while(cin>>n, n)
{
int curmax = ;
sumlen = ;
for(int i=; i<n; ++i)
{
cin>>sticks[i];
curmax = curmax > sticks[i] ? curmax :sticks[i];
sumlen += sticks[i];
}
for(int fac = curmax; fac <= sumlen; ++fac)
{
if(sumlen%fac == )
{
memset(visit, false, sizeof(visit));
if(Traverse(fac))
{
cout<<res<<endl;
break;
}
}
}
} return ;
}

自己后来又重新写了一遍,写的过程中感觉还是对回溯的理解还是不够深,回溯本是暴力的一种,所以这题也能看到一层一层搜索的路径,没有太多的技巧,都是根据题目的特性找规律,充分利用从而写出剪枝的条件,避免了超时,效率也更高。

【AC代码】

 #include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define MAXN 1000 using namespace std; int sticks[MAXN];
bool visit[MAXN];
int n, length, sum, sumlen; bool cmp(const int& a, const int& b)
{
return a>b;
} bool Traverse(int num, int len, int cur)
{
if(num == sum) return true;
for(int i=cur; i<n; ++i)
{
if(!visit[i] && !(i && !visit[i-] && sticks[i] == sticks[i-]))
{
if(len+sticks[i] == length)
{
visit[i] = true;
if(Traverse(num+, , )) return true;
visit[i] = false;
return false;
}
else if(len+sticks[i] < length)
{
visit[i] = true;
if(Traverse(num, len+sticks[i], i+)) return true;
visit[i] = false;
if(len == ) return false;
}
}
}
return false;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("F:\\test\\input.txt", "r", stdin);
#endif // ONLINE_JUDGE
while(cin>>n, n)
{
int curmax = ;
sumlen = ;
for(int i=; i<n; ++i)
{
cin>>sticks[i];
sumlen += sticks[i];
}
sort(sticks, sticks+n, cmp);
for(int fac = sticks[]; fac <= sumlen; ++fac)
{
if(sumlen%fac == )
{
length = fac;
sum = sumlen/fac;
memset(visit, false, sizeof(visit));
if(Traverse(,,)) break;
}
}
cout<<length<<endl;
} return ;
}

UVa 307 - Sticks的更多相关文章

  1. POJ 1011 / UVA 307 Sticks

    中文题 (一般都比较坑) 思路:DFS (感谢学长的幻灯片) 这破题把我折腾惨了!!!搞了n天 // by Sirius_Ren #include <cstdio> #include &l ...

  2. Sticks(UVA - 307)【DFS+剪枝】

    Sticks(UVA - 307) 题目链接 算法 DFS+剪枝 1.这道题题意就是说原本有一些等长的木棍,后来把它们切割,切割成一个个最长为50单位长度的小木棍,现在想让你把它们组合成一个个等长的大 ...

  3. 【Uva 307】Sticks

    [Link]: [Description] 给你最多n个棍子; (n< = 64) 每根棍子长度(1..50) 问你这n根棍子,可以是由多少根长度为x的棍子分割出来的; x要求最小 [Solut ...

  4. uva 307

    排序之后再剪枝,有点神 #include <cstdio> #include <cstdlib> #include <cmath> #include <map ...

  5. 紫书 习题7-14 UVa 307(暴搜+剪枝)

    这道题一开始我想的是在排序之后只在头和尾往中间靠近来找木块, 然后就WA, 事实证明这种方法是错误的. 然后参考了别人的博客.发现别人是直接暴搜, 但是加了很多剪枝, 所以不会超时. 我也想过这个做法 ...

  6. hduoj 1455 && uva 243 E - Sticks

    http://acm.hdu.edu.cn/showproblem.php?pid=1455 http://uva.onlinejudge.org/index.php?option=com_onlin ...

  7. UVA题目分类

    题目 Volume 0. Getting Started 开始10055 - Hashmat the Brave Warrior 10071 - Back to High School Physics ...

  8. uva 10003 Cutting Sticks 【区间dp】

    题目:uva 10003 Cutting Sticks 题意:给出一根长度 l 的木棍,要截断从某些点,然后截断的花费是当前木棍的长度,求总的最小花费? 分析:典型的区间dp,事实上和石子归并是一样的 ...

  9. UVA 10003 Cutting Sticks 区间DP+记忆化搜索

    UVA 10003 Cutting Sticks+区间DP 纵有疾风起 题目大意 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用 输入输出 第一行是木棍的 ...

随机推荐

  1. linq 分类

    linq技术为我们开发人员提供了五个比较实用的数据访问类型: LinQ to Object:可以允许对内存中的类对象查询. LinQ to DataSet:可以对内存中的DataSet缓存数据,执行数 ...

  2. Maven基本操作命令

    1.mvn package 此命令包含一系列过程:validate-->compile-->test-->package Maven根据pom文件里packaging的配置,决定是生 ...

  3. DirectX 3D 之C#开发

    C#下进行directX的3D开发,一个旋转的4棱锥的例子. 建议看两个文档<Managed DirectX 9图形和游戏编程简略中文文档>和<Managed DirectX 9 S ...

  4. python判断文件目录是否存在

    import os os.path.isfile('test.txt')  # 如果不存在就返回False os.path.exists(directory)  # 如果目录不存在就返回False o ...

  5. sort+结构体实现二级排序

    之前介绍的sort函数由于其效率较高,使用较为简单让我用起来那叫一个爽,今天再写一篇使用sort+结构体实现二级排序的方法. 还是先想个问题吧,比如我想输入5个同学的名字和身高,然后得到他们身高的降序 ...

  6. 数据库MySQL-Oracle-DB2-SQLServer分页查询

    1. MySQL分页查询 (1)关键字: LIMIT beginIndex, maxRow (2)示例: LIMIT子句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数. 如果给出 ...

  7. UVa 10969 (圆与圆之间的覆盖问题) Sweet Dream

    题意: 有n个按先后顺序放置的不同大小不同位置的圆,求所有可见圆弧的长度. 分析: 这道题应该是大白书上例题 LA 2572 (求可见圆盘的数量) Kanazawa 的加强版,整体框架都差不多. 对于 ...

  8. django - settings

    1.doc - https://docs.djangoproject.com/en/1.6/topics/settings/ from django.conf import settings # 加载 ...

  9. NYOJ-779-兰州烧饼

    [题目链接:NYOJ-779] 兰州烧饼 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述 烧饼有两面,要做好一个兰州烧饼,要两面都弄热.当然,一次只能弄一个的话,效率 ...

  10. Delphi 2010 安装及调试

    呵呵,毫不客气地说,Delphi 2010 这个版本可以算是 Delphi 的一个“里程碑”,为什么这么说?因为这个版本实现了几个 Delphi 应该有却一直没有的功能 Delphi 2010 的新功 ...