poj1011 (Sticks)

2024-08-31 12:32
文章标签 sticks poj1011

本文主要是介绍poj1011 (Sticks),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

自己加了些注释和排序方法

转载请注明出处:優YoU   http://user.qzone.qq.com/289065406/blog/1311647833

解题思路:

DFS+剪枝

POJ2362的强化版,重点在于剪枝

令InitLen为所求的最短原始棒长,maxlen为给定的棒子堆中最长的棒子,sumlen为这堆棒子的长度之和,那么InitLen必定在范围[maxlen,sumlen]中

根据棒子的灵活度(棒子越长,灵活度越低) DFS前先对所有棒子降序排序

 

剪枝:

1、  由于所有原始棒子等长,那么必有sumlen%Initlen==0;

2、  若能在[maxlen,sumlen-InitLen]找到最短的InitLen,该InitLen必也是[maxlen,sumlen]的最短;若不能在[maxlen,sumlen-InitLen]找到最短的InitLen,则必有InitLen=sumlen;

3、  由于所有棒子已降序排序,在DFS时,若某根棒子不合适,则跳过其后面所有与它等长的棒子;

4、  最重要的剪枝:对于某个目标InitLen,在每次构建新的长度为InitLen的原始棒时,检查新棒的第一根stick[i],若在搜索完所有stick[]后都无法组合,则说明stick[i]无法在当前组合方式下组合,不用往下搜索(往下搜索会令stick[i]被舍弃),直接返回上一层

 

#include<iostream>
#include<algorithm>
using namespace std;
int cmp(const void* a,const void* b)
{return *(int*)b-*(int*)a;
}
int cmp2(int a,int b)
{return a>b;
}
int n;  //木棒数量
bool dfs(int* stick,bool* vist,int len,int InitLen,int s,int num)  //len:当前正在组合的棒长  InitLen:目标棒长  
{                                                                  //s:stick[]的搜索起点  num:已用的棒子数量if(num==n)return true;int sample=-1;	//sample即发现当前用该长度的去拼凑是不会成功的,当有相等长度的出现时直接跳过.\因为排序过的,所有可以只用一个变量标记很多个相等的stick[]for(int i=s;i<n;i++){if(vist[i] || stick[i]==sample)  //剪枝3,等长的木棒只搜索一次continue;vist[i]=true;	//为了区别之前已经拼凑好的木棒if(len+stick[i]<InitLen){if(dfs(stick,vist,len+stick[i],InitLen,i,num+1)) //一发现可以拼成即返回return true;elsesample=stick[i];}else if(len+stick[i]==InitLen)	//拼成+一个{if(dfs(stick,vist,0,InitLen,0,num+1))	//拼下一个return true;elsesample=stick[i];}vist[i]=false;if(len==0)  //剪枝4,构建新棒时,对于新棒的第一根棒子,在搜索完所有棒子后都无法组合break;  //则说明该棒子无法在当前组合方式下组合,不用往下搜索(往下搜索会令该棒子被舍弃),直接返回上一层}return false;
}
int main(void)
{while(cin>>n && n){int* stick=new int[n];bool* vist=new bool[n];int sumlen=0;for(int i=0;i<n;i++){cin>>stick[i];sumlen+=stick[i];vist[i]=false;}//qsort(stick,n,sizeof(stick),cmp);sort(stick,stick+n,cmp2);//sort(stick,stick+n);//reverse(stick,stick+n);int maxlen=stick[0];   //最大的棒为InitLen的搜索起点bool flag=false;//剪枝1,若能在[maxlen,sumlen-InitLen]找到最短的InitLen,该InitLen必也是[maxlen,sumlen]的最短for(int InitLen=maxlen;InitLen<=sumlen-InitLen;InitLen++)  //InitLen:原始棒长{   //剪枝2,InitLen必是sumlen的约数(InitLen<=sumlen-InitLen:意思不就是至少有两个木棒)if(!(sumlen%InitLen) && dfs(stick,vist,0,InitLen,0,0)){cout<<InitLen<<endl;flag=true;break;}}if(!flag)printf("%d\n",sumlen);delete stick;delete vist;}return 0;
}

这篇关于poj1011 (Sticks)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1123909

相关文章

【UVA】10003-Cutting Sticks(动态规划、矩阵链乘)

一道动态规划题,不过似乎可以用回溯水过去,回溯的话效率很烂的。 13988658 10003 Cutting Sticks Accepted C++ 1.882 2014-08-04 09:26:49 AC代码: #include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include

CF 258A. Game With Sticks

http://codeforces.com/contest/451/problem/A 很有意思的题目,大水 A. Game With Sticks time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output

Uva | Cutting Sticks

原题 You have to cut a wood stick into pieces. The most affordable company, The Analog Cutting Machinery,Inc. (ACM), charges money according to the length of the stick being cut. Their procedure of wor

Sticks ---- 深度优先搜索+剪枝优化

这是我第一道接触剪枝算法的题目,剪枝的用处就是为了优化深度优先搜索的时间复杂的,使其代码跑的更快。 Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 118677 Accepted: 27381 Description George took sticks of the same length and cut

[LightOJ 1342] Aladdin and the Magical Sticks (期望的线性性质+几何分布+邮票收集问题)

LightOJ - 1342 有 N根棍子,每根棍子都有一个权值 其中有若干根可识别的,若干根不可识别的 抽到了可识别的棍子,就不放回,抽到了不可识别的,就要放回 问所有棍子都至少被抽过一次后的期望权值和 根据期望的线性性, E(CX)=CE(X) E(CX) = CE(X) 所以可以对每根棍子求一下它被抽到的期望次数,再乘以它的权值 对于不可识别的棍子,由于它被抽到的概率

[Codeforces 451A] Game With Sticks (博弈)

Codeforces - 451A N根横向木棍,M根纵向木棍组成了一个网格图 每次可以选择一个交点,去掉所有通过这个交点的木棍 两个人交替进行这个游戏,问最后谁能胜利 每次选择的一个交点,必然去掉了一根横向木棍和纵向木棍 所以每次 N和 M都减一 当其中有一个为 0的时候,就是先手必败态 所以只和 N、M中较小的那个的奇偶性有关 #pragma comment(link

uvalive 2322 Wooden Sticks(贪心)

题目连接:2322 Wooden Sticks 题目大意:给出要求切的n个小木棍 , 每个小木棍有长度和重量,因为当要切的长度和重量分别大于前面一个的长度和重量的时候可以不用调整大木棍直接切割, 否则要进行调整。现在要求求出一个序列, 使得调整的次数最少, 输出调整的次数。 解题思路:将n个小木棍先按照 长度和重量的大小排序,然后按照顺序将小木棍分堆,可入堆的要求是长度和重量大于当

poj 2513 Colored Sticks

题目链接:点击打开链接 Description You are given a bunch(群) of wooden sticks. Each endpoint(端点) of each stick is colored with some color. Is it possible to align(结盟) the sticks in a straight line such that

Cutting Sticks UVA - 10003 (区间Dp)

链接:点击打开链接 题目大意:有一根木棍长度为L,然后有N个切割点,将木棍切割成n+1段,当切割长度为Li时,那么需要Li的费用.例如有一个长度为10的木棍,切割点在2,4,7位置上,如果顺序切割的话:  1、首先长度为10,在2位置切割,那么sum+=10 2、再在剩下的长度为8的长度中切割4位置,那么sum+=8 3、再在剩下长度为6中切7位置,那么sum+=6==24 而如果按顺序

杭电OJ 1051:Wooden Sticks

这个题目的大意是有一个处理木材的机器,处理第一根木材的时候需要调整,后面的木材如果长度不小于前面的木材并且重量也不小于前面的木材则机器不需要重新调整,否则就需要调整,调整一次花费的时间为1,问机器最少要调整几次? 这个问题其实可以转换为求最长递减子序列。转化过程:先对多所有的木材按长度从小到大排序,然后按重量求最长递减子序列,子序列元素的个数就是机器要调整的次数,因为这个序列中的元素是不可能排在