zoukankan      html  css  js  c++  java
  • POJ1011 Sticks

    题目来源:http://poj.org/problem?id=1011

    题目大意:George有一些等长的木棍,他把这些木棍随机地砍断,砍断后的木棍最多50单位长。现在他想把木棍拼回原来的长度,但他已经忘记了原来有多少根木棍和原来的木棍有多长。请帮他设计一个程序计算原始木棍的最小长度。所有木棍的长度都是正整数单位长度。

    输入:含多个数据块,每个数据块为一个测试用例,第一行为一个整数,表示砍断后有多少根木棍,最大为64.第二行为每根木棍的长度,以空格分开。输入的最后一行为0。

    输出:每个测试用例对应一行,含一个整数:最小的可能原始木棍长度。


    Sample Input

    9
    5 2 1 5 2 1 5 2 1
    4
    1 2 3 4
    0
    

    Sample Output

    6
    5

    对问题进行分析发现,我们可以把可能解确定在一个范围内:

      1.原始长度最小为砍断后最长的那根木棍的长度

      2.因为木棍的总长度不变,那么原来木棍最长为现有所有短木棍拼起来的长度

      3.因为木棍都为整数单位长度,且对木棍进行砍断后,木棍数目只会增加而不可能减少,所以若总长度不能整除一个候选解或某候选解对应的原始木棍根数多于现在木棍的根数,显然都不可能成为可行解

      基于以上的思想,用DFS+剪枝实现。

     1 //////////////////////////////////////////////////////////////////////////
     2 //        POJ1011 Sticks
     3 //        Memory: 284K        Time: 16MS
     4 //        Language: C++        Result: Accepted
     5 //////////////////////////////////////////////////////////////////////////
     6 
     7 #include <iostream>
     8 #include <stdlib.h>
     9 using namespace std;
    10 
    11 bool buff[64];
    12 int stick[70];
    13 bool visit[70];
    14 int n;
    15 
    16 int campare(const void * a, const void * b) {
    17     return *((int *)b) - *((int *)a);
    18 }
    19 
    20 bool dfs(int * stick, bool * visit, int len, int initLength, int start, int num) {
    21     if (num == n) {
    22         return true;
    23     }
    24     int sample = -1;
    25     for (int i = start; i < n; i++) {
    26         if (visit[i] == true || stick[i] == sample) {
    27             continue;
    28         }
    29         visit[i] = true;
    30         if (len + stick[i] == initLength) {
    31             if (dfs(stick, visit, 0, initLength, 0, num + 1)) {
    32                 return true;
    33             } else {
    34                 sample = stick[i];
    35             }
    36         } else if (len + stick[i] < initLength) {
    37             if (dfs(stick, visit, len + stick[i], initLength, i, num + 1)) {
    38                 return true;
    39             } else {
    40                 sample = stick[i];
    41             }
    42         }
    43         visit[i] = false;
    44         if (len == 0) 
    45             break;
    46     }
    47     return false;
    48 }
    49 
    50 int main(void) {
    51     while (true) {
    52         int totalLength = 0;
    53         cin >> n;
    54         if (n == 0) {
    55             break;
    56         }
    57         for (int i = 0; i < n; i++) {
    58             cin >> stick[i];
    59             visit[i] = false;
    60             totalLength += stick[i];
    61         }
    62         qsort(stick, n, sizeof(int), campare);
    63         int maxLength = stick[0];
    64         bool findSolution = false;
    65         //检验每个可能的可行解
    66         for (int initLength = maxLength; initLength <= totalLength - initLength; initLength++) {
    67             //isSolution标记是否找到可行解
    68             int oriCount = 0;
    69             //totalLength能被i整除,oriCount表示原始木棍数
    70             if (totalLength % initLength != 0) {
    71                 continue;
    72             }
    73             if(dfs(stick, visit, 0, initLength, 0, 0) == true) {
    74                 cout << initLength << endl;
    75                 findSolution = true;
    76                 break;
    77             }
    78         }
    79         if (!findSolution) {
    80             cout << totalLength << endl;
    81         }
    82     }
    83     system("pause");
    84     return 0;
    85 }
    View Code
  • 相关阅读:
    echarts 报表使用
    Eclipse Java注释模板设置详解
    简单实现支付密码输入框 By HL
    一个label 混搭不同颜色,不同字体的文字.. by 徐
    有关MVC设计模式 #DF
    自定义粘贴板-陈鹏
    TableView 常用技巧与功能详解
    ios 类别和扩展-赵小波
    推荐一本书--《浪潮之巅》(完整版的哦)----董鑫
    iOS block的用法 by -- 周傅琦君
  • 原文地址:https://www.cnblogs.com/dengeven/p/3226805.html
Copyright © 2011-2022 走看看