zoukankan      html  css  js  c++  java
  • POJ 1011 Sticks

    题意:一开始你有若干个等长的木棍,后来把他们随机砍成几小段,问一开始的木棍最短多长。

    解法:DFS + 剪枝。悲剧的发现自己已经不太会搜索了。

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define LL long long
    using namespace std;
    int n, s, len;
    bool vis[70];
    int stick[70];
    bool cmp(int a, int b)
    {
        return a > b;
    }
    bool dfs(int remlen, int pos, int num)//remlen是当前拼的大木棍剩余长度,pos是枚举到哪一个小木棍,num是拼到哪一根大木棍
    {
        if(num == s)//剪枝,如果已经拼到最后一根大木棍则一定能拼成,不需要搜索下去
            return true;
        if(remlen == 0)//剪枝,当一根大木棍拼好,找到第一根未使用的小木棍进行搜索
        {
            int i = 0;
            while(vis[i])
                i++;
            vis[i] = true;
            if(dfs(len - stick[i], i, num + 1))
                return true;
            vis[i] = false;
            return false;
        }
        for(int i = pos + 1; i < n; i++)
        {
            if(!vis[i])
            {
                if(!vis[i - 1] && (stick[i] == stick[i - 1]))//剪枝,如果前一根小木棍没有被使用而且前一根小木棍跟当前小木棍长度相同则没有必要搜索下去
                    continue;
                if(!vis[i] && (remlen >= stick[i]))
                {
                    vis[i] = true;
                    if(dfs(remlen - stick[i], i, num))
                    return true;
                    vis[i] = false;
                    if(stick[i] == remlen)
                    break;
                }
            }
        }
        return false;
    }
    int main()
    {
        while(~scanf("%d", &n) && n)
        {
            int maxx = 0, sum = 0;
            for(int i = 0; i < n; i++)
            {
                scanf("%d", &stick[i]);
                maxx = max(maxx, stick[i]);
                sum += stick[i];
            }
            sort(stick, stick + n, cmp);//剪枝,从大到小排序
            bool flag = true;
            for(int i = maxx; i <= sum / 2; i++)//原来木棍的长度一定是木棍和的因数,所以只需要枚举到sum / 2, 如果在这个范围内没有枚举到则答案是木棍长度的和
            {
                if(sum % i)//木棍长度是木棍和的因数
                    continue;
                memset(vis, 0, sizeof vis);
                s = sum / i;
                len = i;
                vis[0] = true;
                if(dfs(len - stick[0], 0, 1))
                {
                    flag = false;
                    printf("%d
    ", i);
                    break;
                }
            }
            if(flag)
                printf("%d
    ", sum);
        }
        return 0;
    }
    

      

  • 相关阅读:
    turtle 绘制爱心
    数据库总结
    anconda安装使用
    爬虫之存储库MongoDB
    【python】代码换行的几种方法
    【python】 合并列表的方法
    【notebook】常用在线notebook总结
    【PDF】PDF无法注释的一种解决方案
    【课程】MIT深度学习课程:架起理论与实践的桥梁
    【今日CV 视觉论文速览】Thu, 21 Feb 2019
  • 原文地址:https://www.cnblogs.com/Apro/p/4366383.html
Copyright © 2011-2022 走看看