zoukankan      html  css  js  c++  java
  • 如何从125个数中找出21个数使其等于固定值

      在CSDN论坛看到有人问了这个问题,还挺有趣的,关键是他这个的数据量是非常大

      原链接http://bbs.csdn.net/topics/391897373

      这一题肯定不能用枚举(其实这样的题都不用枚举),一个是时间太长了,第二就是储存容量也不够,这一题大概1e+20左右的大小,跑半天不说,还是会溢出的,即使剪枝

      我一开始想到用分治的方法,后来想了一下21个数实在是太大了,而且他的数据量也不是小,是120+个数,所以我想到了用背包,其实这类的问题都可以用背包问题来解决的。

      但是他这一题不是问选多少个物品小于什么重量找最大价值的题,那我们就改一下,把选的物品的个数变成价值,而且除非能直接到达固定值,否则最大选的个数就一直是select-1

      我自己做的时间复杂度也是挺大的,因为我是对总量进行背包的,所以时间复杂度是0(C*P*N),在我的机子跑79S。。。说实话很慢

      如果要优化的话,可以把数拆分成一个一个区域,然后再背包,这样包容量可以减少好几个数量级,跑起来相当快了

      

    #include <iostream>
    #include <functional>
    #include <algorithm>
    #include <time.h>
    #define SIZE 125
    #define MAX 6531127
    
    using namespace std;
    
    static int input[SIZE] = { 55000, 55000, 63500, 96120, 97000, 
                                102350, 102350, 132510, 135370, 140000, 
                                144000, 166800, 167530, 169800, 178300, 
                                178300, 178800, 179300, 181000, 181000, 
                                181000, 181000, 181000, 181000, 181000, 
                                182200, 183500, 185684, 188800, 188800, 
                                189800, 190800, 190800, 190800, 195684,
                                198000, 199626, 199626, 199800, 199800, 
                                199900, 201000, 208700, 209800, 209800, 
                                209800, 209800, 209800, 219000, 219000, 
                                219000, 219000, 219800, 220000, 220000, 
                                220000, 220130, 225600, 228000, 228000, 
                                229434, 229800, 229800, 229800, 229800, 
                                235000, 238800, 240000, 240900, 244800, 
                                247800, 248000, 249800, 249800, 249800, 
                                249800, 249800, 249800, 249800, 249800, 
                                250000, 250000, 250000, 250000, 257000,
                                260800, 279800, 279800, 279800, 279800,
                                280340, 285000, 295000, 295000, 295000, 
                                298000, 299000, 300000, 300000, 300000, 
                                313701, 328897, 337300, 345000, 350000, 
                                350000, 350000, 350064, 350064, 350064,
                                350064, 350064, 429800, 430290, 440154, 
                                472200, 472200, 487305, 500500, 506300, 
                                512226, 544110, 749000, 820000, 1100000 }, goal_select = 21;
                                
    static struct _set
    {
        char _num_sum[5], _select[5][21];
        int  rep;
    }bag1[MAX + 1], bag2[MAX + 1], *tmp, *dp1, *dp2;
    
    void Print_Select(struct _set *goal,const int rep)
    {
        int pos_stop = goal[MAX]._num_sum[rep];
        cout << "The items are :" << endl;
        for (int i = 0; i < pos_stop; i++)
            cout << goal[MAX]._select[rep][i] + 1 << ": " << input[goal[MAX]._select[rep][i]] << endl;
    }
    
    void Copy(const int m1, const int m2)
    {
        memcpy(dp2[m2]._num_sum, dp1[m1]._num_sum, sizeof(dp2[m2]._num_sum));
        memcpy(dp2[m2]._select, dp1[m1]._select, sizeof(dp2[m2]._select));
        dp2[m2].rep = dp1[m1].rep;
    }
    
    int Max(const int x, const int y)
    {
        return x > y ? x : y;
    }
    
    void Merge_Bound(struct _set *pos1, struct _set *pos2, struct _set *goal,const int stuff)
    {
        int ptr_dp1 = 0, ptr_dp2 = 0, tmp_sum, tmp_rep = 0;
        int up_bound = Max(pos1->_num_sum[pos1->rep - 1], pos2->_num_sum[pos2->rep - 1]) + 1;
    
        for (int i = 1; i <= up_bound; i++)
        {
            if (pos1->rep != 0//0代表不合法
                && (pos1->_num_sum)[ptr_dp1] + 1 <= goal_select - 1
                && (pos1->_num_sum)[ptr_dp1] + 1 == i)
            {
                (goal->_num_sum)[tmp_rep] = tmp_sum = (pos1->_num_sum)[ptr_dp1] + 1;
                memcpy((goal->_select)[tmp_rep], (pos1->_select)[ptr_dp1], sizeof((goal->_select)[tmp_rep]));
                (goal->_select)[tmp_rep][tmp_sum - 1] = stuff - 1;
                ptr_dp1++;
                tmp_rep++;
            }
            else if (pos2->rep != 0
                && (pos2->_num_sum)[ptr_dp2] == i)
            {
                (goal->_num_sum)[tmp_rep] = (pos2->_num_sum)[ptr_dp2];
                memcpy((goal->_select)[tmp_rep], (pos2->_select)[ptr_dp2], sizeof((pos2->_select)[ptr_dp2]));
                ptr_dp2++;
                tmp_rep++;
            }
        }
        goal->rep = tmp_rep;
    }
    
    bool Search(void)
    {
        int pos, num_sum;
        dp1[0].rep = 1;
    
        for (int i = 1; i <= SIZE; i++)
        {
            dp2[0].rep = 1;
            for (int j = 1; j < input[i - 1]; j++)
                Copy(j, j);
            for (int j = input[i - 1]; j <= MAX; j++)
            {
                if (j == MAX && dp1[MAX - input[i - 1]]._num_sum[dp1[MAX - input[i - 1]].rep - 1] + 1 == goal_select)//直接输出
                {
                    Copy(MAX - input[i - 1], MAX);
                    pos = dp1[MAX - input[i - 1]].rep - 1;
    
                    dp2[MAX]._num_sum[pos]++;
                    num_sum = dp2[MAX]._num_sum[pos];
    
                    dp2[MAX]._select[pos][num_sum - 1] = i - 1;
                    Print_Select(dp2, dp2[MAX].rep - 1);
                    return true;
                }
                Merge_Bound(&dp1[j - input[i - 1]], &dp1[j], &dp2[j], i);
            }
            tmp = dp1; dp1 = dp2; dp2 = tmp;
        }
        return false;
    }
    
    int main(void)
    {
        dp1 = bag1; dp2 = bag2;
        time_t t1 = clock();
        if (Search())
            cout << "SUCCESS" << endl;
        else
            cout << "FAIL" << endl;
        time_t t2 = clock();
        cout << t2 - t1 << "ms" << endl;
        system("pause");
        return EXIT_SUCCESS;
    }
  • 相关阅读:
    js获取url参数方法
    JQuery ajax 传递数组
    删除数组中的重复元素
    jquery load的使用
    css3 圆角
    一个项目最忌讳什么
    Lambda 表达式笔记
    KE ASP.NET取到kindeditor 编辑器数据
    ADO.NET
    .NET中Bind和Eval的区别
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5169310.html
Copyright © 2011-2022 走看看