POJ1011-Sticks

Sticks
Time Limit 1000MS Memory Limit 10000K
Total Submissions 117588 Accepted 27100
Description
翻译:
问题描述:乔治拿来一组等长的木棒,将它们随机地裁断,使得每一节木棒的长度都不超过50个长度单位。然后他又想把这些木棒恢复到为裁截前的状态
,但忘记了木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棒的长度都用大于零的整数表示
输入:
由多个案例组成,每个案例包括两行。第一行是一个不超过64的整数,表示裁截之后共有多少节木棒。第二行是经过裁截后,所得到的各节木棒的长度。
在最后一个案例之后,是零。
输出:
为每个案例,分别输出木棒的可能最小长度。每个案例占一行。
Sample Input
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
Sample Output
6
5

解题思路
初始状态:有N节木棒。最终状态:这N节木棒恰好被拼接成若干根等长的木棒。
从初始状态到最终状态最多有多少条不同的“路径”(指原始单个木棒可能的长度)?
Sum/maxParts。其中Sum是全部N节木棒的长度之和,maxParts是最
长一节木棒的长度

每条“路径”对应一个木棒的长度。从木棒长度最小的那条可能“路径”开始,如果成功地的找到了这条“路径”,就解决了问题DFS深搜
构造一条木棒长度为L的“路径”:拼接木棒
在未被拼接的木棒中,找出一节最长的,开始拼接

从未拼接的木棒中,选择一个长度合适的木棒,使得拼接后的木棒长度≤L1.找到了:
在前面的拼接过程中曾试图用过相同长度的一节其他木棒,但发现这样拼接不成功,继续寻找能够进行拼接的木棒

把找到的那节木棒拼接上去。

   继续进行拼接   继续拼接成功,找到了“路径”

   继续拼接不成功,把刚拼接的那节木棒拿下来,继续找下一个合适的未   拼接木帮

2.没有找到:拼接失败

bool  Dfs(int nUnusedSticks, int nLeft ) ;

表示: 当前有nUnusedSticks根未用木棒,而且当前正在拼的那根棍子比假定的棍子长度短了nLeft, 那么在这种情况下能全部否拼成功。

AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int len[100],flag[100],L;
int n,sum;
int cmp(int a,int b)
{
    if(a!=b) return a>b;
}
int DFS(int num,int nLeft)
// nLeft表示当前正在拼的棍子和L比还缺的长度
{
   int i;
   if(num==0&&nLeft==0)
   return 1;
   if(nLeft==0)//一根刚刚拼完
   nLeft=L;//开始拼新的一根
   for(i=0;i<n;i++)
   {
      if(!flag[i]&&len[i]<=nLeft)//如果此棒没有用过而且小于等于和L比还缺的长度
      {
         if(i>0)
         {
            if(flag[i-1]==0&&len[i]==len[i-1])
            continue;//剪枝1
         }
         flag[i]=1;
         if(DFS(num-1,nLeft-len[i]))
         return 1;
         else
         {
             flag[i] = 0;//说明不能用i作为
						//第1条,
						//那么要拆以前的
						//棍子,i还可能用
						//在以前的棍子里,
					     //因此要 flag[i]=0;
			 if(len[i]==nLeft||nLeft==L)
		     return 0;//剪枝2

         }
      }
   }
   return 0;
}
int main()
{
    int i;
    while(scanf("%d",&n)&&n)
    {
       sum=0;
       memset(len,0,sizeof(len));
       for(i=0;i<n;i++)
       {
          scanf("%d",&len[i]);
          sum+=len[i];
       }

       sort(len,len+n,cmp);

       for(L=len[0];L<=sum/2;L++)//从最长的那一根棒开始累加计算
       {
          if(sum%L)//木棒至少要有两截
          continue;
          memset(flag,0,sizeof(flag));//记录木棒是否被用过
          if(DFS(n,L))
          {
             printf("%d\n",L);
             break;
          }
       }
       if(L>sum/2)
       printf("%d\n",sum);//只有一根木棒被剪成几分
    }
    return 0;
}
时间: 2024-10-29 06:42:13

POJ1011-Sticks的相关文章

算法-C/C++杭电1501题Wooden sticks 求挑错

问题描述 C/C++杭电1501题Wooden sticks 求挑错 DescriptionThere is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time called setup

POJ 2653 Pick-up sticks:计算几何 求线段交点

POJ 2653:http://poj.org/problem?id=2653 题意:题意很简单,就是在地上按顺序撒一对木棒,看最后有多少是被压住的,输出没有被压住的木棒的序号.有点坑的就是没说清楚木棒怎么算压住,也不知道是不是规范相交...我就判断了一下包括端点重合跟部分相交的. 思路:一开始我想的是从后往前遍历,找到每一条边,看他是不是压到之前的边了,如果压到了,就把之前的变标记一下,最后统计没被标记过的,但是TLE了...就只能从前面开始找,遍历每一条边是否被后面的压过了,压过了就直接br

算法:uva 10003 Cutting Sticks (区间dp)

题目大意 一根长为l的木棍,上面有n个"切点",每个点的位置为c[i] 要按照一定顺 序把每个点都砍段,最后变成了n+1段 每砍一次,就会有一个花费,例如长度为10,"切点"为2,那么砍完 后会变成两段2,8, 那么花费为2+8=10 如果有多个"切点",那么不同顺序切会得到不同的花费. 最小 花费是多少? 思路 注意要增加一个c[n] = l f(i, j) 表示(i,j)区间的最小花费 f(i, j) = min{ f(i,k)+f(k+1,

UVa 10003 Cutting Sticks (DP)

10003 - Cutting Sticks Time limit: 3.000 seconds http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&page=show_problem&problem=944 You have to cut a wood stick into pieces. The most affordable company, The Ana

hdu 1051 Wooden Sticks(贪心)

Wooden Sticks Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 15215    Accepted Submission(s): 6242 Problem Description There is a pile of n wooden sticks. The length and weight of each stick a

计算几何-hdoj-1147-Pick-up sticks

Pick-up sticks Problem Description Stan has n sticks of various length. He throws them one at a time on the floor in a random way. After finishing throwing, Stan tries to find the top sticks, that is these sticks such that there is no stick on top of

贪心算法 WOODEN STICKS 实例代码_C 语言

Problem DescriptionThere is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time, called setup time, for the machine to

poj2513Colored Sticks(无向图的欧拉回路)

/* 题意:将两端涂有颜色的木棒连在一起,并且连接处的颜色相同! 思路:将每一个单词看成一个节点,建立节点之间的无向图!判断是否是欧拉回路或者是欧拉路 并查集判通 + 奇度节点个数等于2或者0 */ #include<cstring> #include<cstdio> #include<algorithm> #define N 2500005*2 using namespace std; int f[N]; int trie[N][26]; int rank[N]; i

poj 2513 Colored Sticks

点击打开链接poj2513 思路: hash+并查集+欧拉路 分析: 1 题目要求给定n个木棒是否可以组成一个满足要求的字符串 2 很明显的判断无向图是否是半欧拉图,首先先判断是否是单连通这一点可以利用并查集,然后在去判断是不是最多两个点的度数为奇数 3 最后一个问题就是怎么把字符串映射成整数,如果利用map肯定是超时的,那么这里就要用到hash,由于这题的数据比较弱我没有处理冲突也过了 代码: #include<cstdio> #include<cstring> #include

POJ2513-Colored Sticks

+ View Code?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354/*<br>思路:类似图论中"一笔画"问题,两根木棒的相连接的端点是一样的颜色,(a,b)--(b,c)--(c, d)....<br>方法:trie树+并查集, 利用trie树建立字符串和某一个节点的映射,并将这些和字符串构成映射的节点建成图