HDU 1455 Sticks

这题让我看解题报告都感觉弱无力的样子,囧rz

题意:

几根原本长度相同的木棒,然后被某人当出气筒剪啊剪啊,剪成好几段,然后,好吧,这时间一长记性就差了,忘了原来这堆木棒的长度。

输出可能的最短长度

如果说思路大概懂,但是代码看不懂,最好的办法就是在纸上模拟,或者把别人代码在计算机上一步一步跟踪调试。

首先原长可能的范围:

最短也比剪断后的最长木棒长(或者相等),最长可能就是由一根木棒剪出来的

另外,原木棒长度必然是木棒总长的因数

 

再解释一下代码中DFS各个参数的含义

bool DFS(int len, int l, int count, int pos)
  • len:假设原木棒长度为len,进行搜索。搜索过程中len是不变的
  • l:一个长为len的木棒,可能是由多个剪断后的木棒拼接而成。l表示当前正在还原的木棒的长度,也就是说还需要一个或多个总长为len-l的木棒就能还原成一个长为len的木棒
  • count:如果总长sum,原长为len,则原来一共有sum/len根木棒,count则记录着已经拼好了多少根长为len的木棒
  • pos:此次要拼的木棒的位置

 

 1 #define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 struct Stick
 9 {
10     int lenth;
11     bool used;    //    该木棒是否已经用于拼接
12 }sticks[55];
13 
14 int n, num, sum;
15 
16 bool cmp(Stick a, Stick b)
17 {
18     return (a.lenth > b.lenth);
19 }
20 
21 bool DFS(int len, int l, int count, int pos)
22 {
23     if(len == sum)
24         return true;
25     if(count == num)
26         return true;    //num根木棒已经全部拼接完成
27     for(int i = pos; i < n; ++i)
28     {
29         if(sticks[i].used)
30             continue;
31         if(len == sticks[i].lenth + l)
32         {
33             sticks[i].used = true;
34             if(DFS(len, 0, count + 1, 0))    //拼好一根,拼下一根
35                 return true;
36             sticks[i].used = false;
37             return false;
38         }
39         else if(len > sticks[i].lenth + l)
40         {
41             sticks[i].used = true;        //一根拼不完,先拼上
42             l += sticks[i].lenth;
43             if(DFS(len, l, count, i + 1))
44                 return true;
45             sticks[i].used = false;
46             l -= sticks[i].lenth;
47             if(l == 0)
48                 return false;        //这一句不是特别理解 =_=!!
49             while(sticks[i].lenth == sticks[i + 1].lenth)
50                 ++i;    //如果两根长度相等,这根长度不符合那么下一根也一定不行
51         }
52     }
53     return false;
54 }
55 
56 int main(void)
57 {
58     #ifdef LOCAL
59         freopen("1455in.txt", "r", stdin);
60     #endif
61 
62     while(scanf("%d", &n) && n)
63     {
64         sum = 0;
65         for(int i = 0; i < n; ++i)
66         {
67             scanf("%d", &sticks[i].lenth);
68             sticks[i].used = false;
69             sum += sticks[i].lenth;
70         }
71         sort(sticks, sticks + n, cmp);
72 
73         for(int len = sticks[0].lenth; len <= sum; ++len)
74         {
75             if(sum % len != 0)
76                 continue;
77             num = sum / len;
78             if(DFS(len, 0, 0, 0))
79             {
80                 printf("%d\n", len);
81                 break;
82             }
83         }
84     }
85     return 0;
86 }
代码君

 

posted @ 2014-08-06 16:53  AOQNRMGYXLMV  阅读(226)  评论(0编辑  收藏  举报