zoukankan      html  css  js  c++  java
  • 动态规划(dynamic programming)

    有一些参考:https://www.sohu.com/a/153858619_466939

    有个题目是这样的:
    有一系列带权重的点集合,问题是求带权重点集中总权重最大的非相邻的独立子集。分析每一步得到:

    $S[n] = max{S[n-1], S[n-2] + v_n->weight}$

    思路: 递归加缓存。刚开始没有加缓存的时候,由于时间复杂度指数级别的O($2^n$),运行很慢,加入缓存后,时间复杂度降为$O(n)$,空间复杂度也为$O(n)$.

    C++代码如下:

    #include <iostream>
    #include <ctime>
    #include <string>
    #include <fstream>
    #include <sstream>
    #include <vector>
    using namespace std;
    /*memorization :递归加缓存优化,备忘录算法
     *如果不用缓存,时间是O(2^n)次方
     *用了缓存后,时间空间复杂度均为O(n)
     *V[n] = max(V[n-1], V[n-2] + vn.weight) 
     *Running time: 0.06s
     */
    
    /*********节点数据存储**********/
    class Node
    {
    public:
        long weight; //权重
        int index;   //索引值
    };
    
    /***********max-weight independent set****************/
    class WIS
    {
    public:
        WIS()   //构造函数
        {
            ifstream fin("mwis.txt");
            string line;
            stringstream stream;
            int cnt = 0;
            if(getline(fin, line))
            {
                stream.clear();
                stream << line;
                stream >> length;
            }
            initWis();
            while(getline(fin, line))
            {    
                long temp;
                stream.clear();
                stream << line;
                stream >> temp;
                nodes[cnt].index = cnt;
                nodes[cnt].weight = temp;
                cnt++;
            }
        }
    /*************初始化每一步的最大权重****************/    
        void initWis()
        {
            nodes.resize(length);
            sum.resize(length);
            weights.resize(length);
            for(int i = 0; i < length; i++)
            {
                weights[i] = 0;
            }
        }
            
        long recursion()
        {
            return dynamic(nodes);  //调用递归
        }
    /******************递归+缓存******************/    
        long dynamic( vector<Node> &nodes1 )
        {
            int le = nodes1.size();
            //如果该节点的最大权重已经被计算过,则返回
            if(weights[le-1]) return weights[le-1];
            
            if( nodes1.size() == 1 )        
            {
                sum[0].push_back(nodes1[0].index + 1);
                weights[0] = nodes1[0].weight;
                return weights[0];   //返回节点数目为1的情况
            }
    
            if( nodes1.size() == 2 ) //节点数目为2的情况
            {
                if(nodes1[0].weight >= nodes1[1].weight)        
                {
                    sum[1].push_back(nodes1[0].index + 1);
                    weights[1] = nodes1[0].weight;
    
                } else {
                    sum[1].push_back(nodes1[1].index + 1);
                    weights[1] = nodes1[1].weight;
                }
                return weights[1];
            }
            
            int len = nodes1.size();
            vector<Node> temp2, temp1;
            temp2.insert( temp2.begin(), nodes1.begin(), nodes1.end() - 2 );
            temp1.insert( temp1.begin(), nodes1.begin(), nodes1.end() - 1 );
            long weight1 = dynamic(temp1); //上一步的最大权重
            long weight2 = dynamic(temp2) + nodes1[len-1].weight; //上上步的最大权重加当前节点权重值
            if( weight1 >= weight2 )
            {
                sum[len-1].insert(sum[len-1].begin(), sum[len-2].begin(), sum[len-2].end());
                weights[len-1] = weight1; //缓存
            } else {
                sum[len-1].insert(sum[len-1].begin(), sum[len-3].begin(), sum[len-3].end());
                sum[len-1].push_back(nodes1[len-1].index + 1); //存节点
                weights[len-1] = weight2;
            }
            return weights[len-1];
        }
    /**********打印************/    
        void print()
        {
            ofstream fout;
            fout.open("output.txt");
            for(int i = 0; i < length; i++)
            {
                fout << i << "th:";
                for(int j = 0; j < sum[i].size(); j++)
                {
                    fout << sum[i][j] << " ";
                }
                fout << " max_weight:" << weights[i] << endl;
            }
    
    
        }
    /*************Reconstruction,得到最大权重独立集**********/
        void reconstruct()
        {
            int i = length - 1;
            while( i > 1)
            {
                if( weights[i-1] >= weights[i-2] + nodes[i].weight )
                {
                    i--;
                } else {
                    path.push_back(i);
                    i = i-2;
                }
            }        
        }
    
    
    public:
        int length;   //节点总数目
        vector<Node> nodes ;
        vector<long> weights;//每一步的最大权重
        vector< vector<long> > sum; //存储每一步的最大权重的点
        vector<int> path;  //max-weight independent set
    
    };
    
    int main()
    {
        clock_t start, end;
        start = clock();
        WIS wis;
        cout << "max_weight_of_IS:" << wis.recursion()  << endl;
        wis.reconstruct();
        wis.print();
        end = clock();
        cout << "running time:" << (double)(end-start)/CLOCKS_PER_SEC << " s" << endl;
        return 0;
    
    }

     还可以用迭代的方法得到,点集的最大权重,速度比递归快的多,但是没有得到具体的点:

        long dynamic()
        {
            long a, b, temp;
            a = nodes[0].weight;
            if(nodes[1].weight > nodes[0].weight)
            {
                b = nodes[1].weight;
            } else {
                b = nodes[0].weight;
            }
            for(int i = 2; i < length; i++)        
            {
            //    a = nodes[i-2].weight;
            //    b = nodes[i-1].weight;
                if(a+nodes[i].weight > b)
                {
                    temp = b;
                    b = a+nodes[i].weight;
                    a = temp;
                } else {
                    a = b;
                }    
            }
            
            return b;
        }
    The Safest Way to Get what you Want is to Try and Deserve What you Want.
  • 相关阅读:
    python ddt 传多个参数值示例
    Appium 输入 & 符号,实际输入&-
    curl 调用jenkins的api
    Android WebView的Js对象注入漏洞解决方案
    Could not find com.android.tools.build:gradle:1.3.0.
    react-native疑难
    win上搭建react-native android环境
    gradle大体内容
    android studio This client is too old to work with the working copy at
    sharedPreference
  • 原文地址:https://www.cnblogs.com/Shinered/p/9155855.html
Copyright © 2011-2022 走看看