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

      

  • 相关阅读:
    C# DES加密解密
    VC SOCKET 压缩通信学习
    ASPX一句话爆破工具
    VC读取文件内容
    VC查找字符串
    (学习记录)代码注入之远程线程篇
    WINSOCK 传送文件
    VC数据类型
    占用字节数求法
    HDU
  • 原文地址:https://www.cnblogs.com/Apro/p/4366383.html
Copyright © 2020-2023  润新知