POJ 1011 Sticks(搜索问题)

原创 2018年04月17日 21:41:48

题目链接
http://bailian.openjudge.cn/practice/1011/

思路一(TLE):
输入数据时,计算出需要枚举的原始棍子长度的上界下界,然后枚举。对每一个stick,将他归到某一组棍子中(如果当前枚举的原始棍子长度为i,一组棍子的总和就应该恰好是i),然后搜索。

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

int N, flag;
int stick[68];
int group[64];      // 每一分组暂时的和

bool cmp(int a, int b)
{
    return a>b;
}

void f(int index, int g_num, int max_num)
{
    // 判断是否超出每一组最大值
    int judge = 1;
    for(int i=0;i<g_num;i++)
    {
        if(group[i] != max_num)
        {
            judge = 0;
            break;
        }
    }
    if(judge == 1)      // 已经确定这样分组可行
    {
        flag = 1;
        return;
    }


    // 对元素i,枚举它属于的组数
    for(int i=0;i<g_num;i++)
    {
        if(group[i]+stick[index] <= max_num)
        {
            group[i] += stick[index];
            f(index+1, g_num, max_num);
            group[i] -= stick[index];
        }
    }
}

int main()
{
    while(scanf("%d", &N) && N>0)
    {
        int tot = 0, max_ele = -9999;   // 枚举的范围
        // 输入stick的值
        for(int i=0;i<N;i++)
        {
            scanf("%d", &stick[i]);
            max_ele = max(max_ele, stick[i]);
            tot += stick[i];
        }

        sort(stick, stick+N, cmp);

        // 最终应该有 tot/i 组
        for(int i=max_ele;i<=tot;i++)
        {
            flag = 0;       // 标记这样分配是否可以
            if(tot%i != 0)
                continue;
            for(int j=0;i<tot/i;j++)
                group[j] = 0;
            f(0, tot/i, i);

            if(flag == 1)
            {
                printf("%d\n", i);
                break;
            }
        }

    }
    return 0;
}

思路2:使用当前的棍子,不断拼接成长度为len的原始棍子。(len的值用枚举获得)由大到小排序,因为更长的棍子对其他棍子约束力更大。对于两个长度相同的棍子,如果前一个棍子匹配失败,后一个棍子不用匹配,即可剪枝,加快速度。

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

int N, flag;
int stick[68];
int vis[68];

bool cmp(int a, int b)
{
    return a>b;
}

void dfs(int tot_used, int now_len, int now_stick, int each_len)
{
    if(flag == 1)
        return;
    if(now_len == 0)        // 找到下一个开头的小棒
    {
        for(int i=0;i<N;i++)
        {
            if(vis[i] == 0)
            {
                vis[i] = 1;
                dfs(tot_used+1, stick[i], i+1, each_len);
                vis[i] = 0;
                return;
            }
        }
    }

    if(now_len == each_len)     // 又拼好一根
    {
        if(tot_used == N)
        {
            flag = 1;
            return;
        }
        dfs(tot_used, 0, 0, each_len);      // 再重新开始拼接
        return;
    }

    for(int i=now_stick;i<N;i++)
    {
        if(vis[i]==0 && now_len + stick[i] <= each_len)
        {
           if(vis[i-1]==0 && stick[i] == stick[i-1])
            continue;      //  不重复搜索:最重要的剪枝。前一根和他一样的,拼不起来,那它也不用试了
           vis[i] = 1;
           dfs(tot_used+1, now_len + stick[i], i + 1, each_len);
           vis[i] = 0;
       }
    }
}

int main()
{
    while(scanf("%d", &N) && N>0)
    {
        int tot = 0, max_ele = -9999;   // 枚举的范围
        // 输入stick的值
        for(int i=0;i<N;i++)
        {
            scanf("%d", &stick[i]);
            max_ele = max(max_ele, stick[i]);
            tot += stick[i];
            vis[i] = 0;
        }

        sort(stick, stick+N, cmp);      // 降序排序

        // 最终应该有 tot/i 组
        for(int i=max_ele;i<=tot;i++)
        {
            flag = 0;       // 标记这样分配是否可以
            if(tot%i != 0)
                continue;
            //f(0, tot/i, i);
            dfs(0, 0, 0, i);

            if(flag == 1)
            {
                printf("%d\n", i);
                break;
            }
        }

    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pku_Coder/article/details/79981359

poj 1011 Sticks

搜索、剪枝、poj 1011 Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 114674 Accepted:...
  • u011721440
  • u011721440
  • 2014-02-21 17:38:26
  • 2187

poj 1011 Java: sticks

题目描述:http://poj.org/problem?id=1011 本题考察的内容是深度优先遍历(DFS),要实现其要求的输出并不困难。但是题目存在时间限制,仅仅使用DFS结果会超时。因此需要我们...
  • u012340794
  • u012340794
  • 2016-02-02 19:47:58
  • 801

POJ1011 Sticks【DFS+剪枝】

题目: Description George took sticks of the same length and cut them randomly until all parts became...
  • huanghanqian
  • huanghanqian
  • 2016-06-12 20:50:50
  • 623

poj(1011)——Sticks(经典的dfs+剪枝)

题目的大致意思是: 现在有n根木棍,然后需要把它们拼成同样长度的木棍,问满足这个条件的最短的长度是多少? 想法嘛:那肯定是dfs把长度搜一遍就好,但问题的关键是这里会超时。那么就要用到剪枝的原理了...
  • ACMer_hades
  • ACMer_hades
  • 2015-07-26 17:12:49
  • 1329

POJ 1011 Sticks (DFS + 剪枝)

Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 135947   Accepted: 31984 ...
  • a2459956664
  • a2459956664
  • 2016-06-08 21:01:18
  • 147

poj 1011 Sticks(搜索+剪枝)

题目链接:http://poj.org/problem?id=1011 题意:给出一些等changde
  • wangxiaoyan381
  • wangxiaoyan381
  • 2014-08-27 14:40:27
  • 335

Sticks POJ - 1011(DFS+剪枝)

George took sticks of the same length and cut them randomly until all parts became at most 50 units ...
  • yinghui_yht
  • yinghui_yht
  • 2017-03-20 11:39:41
  • 69

POJ 1011 最小的木棒 (dfs+剪枝|| 搜索好题)

Description 乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度...
  • h1021456873
  • h1021456873
  • 2016-03-15 00:36:24
  • 707

Poj 1011-Sticks

Poj 1011-Sticks   题意:有n根木棍(n 分析:这题不愧是经典中的经典,很早之前就写过,先后2次都没写出来,然后就放了一段时间,这是第三次了,终于写出来了。 基本思路是我们计算...
  • consciousman
  • consciousman
  • 2016-12-15 21:13:15
  • 493

POJ 1011 Sticks(拯救少林神棍)__深搜

DescriptionGeorge took sticks of the same length and cut them randomly until all parts became at mos...
  • tp7309
  • tp7309
  • 2016-12-03 20:16:52
  • 482
收藏助手
不良信息举报
您举报文章:POJ 1011 Sticks(搜索问题)
举报原因:
原因补充:

(最多只允许输入30个字)