• 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;
    }
    

      

  • 相关阅读:
    Java 基础(六):循环
    Java基础(五):数组
    Java 基础(四):从面试题看String
    Java Grammar(二):运算符
    「每日五分钟,玩转JVM」:指针压缩
    一份让你效率翻倍的年终总结
    「每日五分钟,玩转 JVM」:GC 概览
    「每日五分钟,玩转JVM」:对象内存布局
    「每日五分钟,玩转JVM」:对象从哪来
    Azure Web App (二)使用部署槽切换部署环境代码
  • 原文地址:https://www.cnblogs.com/Apro/p/4366383.html
Copyright © 2020-2023  润新知