zoukankan      html  css  js  c++  java
  • 优先队列2

    1. 题目1:关于工作安排, 每个工作有权重weight和时长length这样两个属性,要求如何安排时间使得$sum_j^n W_j C_j$的值最小。假设一共n个工作,$W_j$为第j个工作的权重,$C_j$为到第j个工作工作完成的时长(加上之前的工作时长)。

    贪心算法有这样两个思路: 按照 (1) weight-length 和 (2)weight/length 的从大到小的思路进行排列,故可以用到优先队列。

    1.1 优先队列按照存储工作的weight-length的从大到小的属性排列,按照从大到小的值对$sum_j^n W_j C_j $进行计算。代码如下

    #include <iostream>
    #include <vector>
    #include <sstream>
    #include <fstream>
    #include <stack>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
    
    class Job
    {
    public:
        int index;  //工作号
        int weight; //权重
        int length; //工作时长
        int we_le; //weight-length
    };
    /***********优先队列Job类自定义比较函数**********/
    class mycompare
    {
        bool reverse;
    public:
        mycompare(const bool & re = false)
        {reverse = re;}
        bool operator() (Job &a, Job &b) const
        {
            if(reverse) return (a.we_le > b.we_le);//实现从小到大的排列
            else {
                if(a.we_le == b.we_le) 
                {
                    return (a.weight < b.weight); // 如果相等,则选择weight大的排在前
                } else {
                    return (a.we_le < b.we_le); //从大到小
                }
            }
        }
    };
    /*************工作安排*******************/
    class JobShedule
    {
    public:
        JobShedule()
        {
            ifstream fin("t.txt");
            string line;
            stringstream stream;
            if(getline(fin,line))
            {
                stream.clear();
                stream << line;
                stream >> count;
            }
            int cnt = 0;
            while(getline(fin, line))
            {
                int _len, _wei;
                stream.clear();
                stream << line;
                stream >> _wei;
                stream >> _len;
                jobs[cnt].index = cnt + 1;
                jobs[cnt].length = _len;
                jobs[cnt].weight = _wei;
                jobs[cnt].we_le = _wei - _len;
                mypq.push(jobs[cnt]);
                cnt++;
            }    
        }
    
    
    /*************计算总的带权重的工作时间**************/    
        void calc_time()
        {
            ofstream fout;
            fout.open("output.txt");
            while(!mypq.empty())                
            {
                Job tmp = mypq.top();
                mypq.pop();
                curLength += tmp.length;
                time += tmp.weight * curLength;
                fout << "tmp time:: " << time << endl;
            }
        }
    
    public:
        int count;
        long long time = 0;
        int curLength = 0;
        Job jobs[12];
        //优先队列,按照工作的weight-length排列队列。
        priority_queue <Job, vector< Job > ,mycompare> mypq;
    };
    
    int main()
    {
        JobShedule jobsh;
        jobsh.calc_time();
        cout << "total time:" << jobsh.time << endl;
        return 0;
    }

    1.2 如果按照工作的weight/length从大到小排列。

    class Job
    {
    public:
        int index;
        int weight;
        int length;
        float ratio; //按照weight/length
    };
    /*************自定义比较函数,按照ratio从大到小排列***************/
    class mycompare
    {
        bool reverse;
    public:
        mycompare(const bool & re = false)
        {reverse = re;}
        bool operator() (Job &a, Job &b) const
        {
            if(reverse) return (a.ratio > b.ratio);//实现从小到大的排列
            else {
                if(a.ratio == b.ratio) 
                {
                    return (a.weight < b.weight); // 如果相等,则选择weight大的排在前
                } else {
                    return (a.ratio < b.ratio); //从大到小
                }
            }
        }
    };

    2.prim算法的简单实现,代码比较烂。对cost的最小值进行选取。

    #include <iostream>
    #include <string>
    #include <stack>
    #include <fstream>
    #include <sstream>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    /**********边表************/
    class EdgeNode
    {
    public:
        int adjvex;
        int cost;
        int head;
        EdgeNode *next;
        EdgeNode(int _head, int _adj, int _cost,EdgeNode *n = NULL) : head(_head), adjvex(_adj), cost(_cost), next(n) {}
    };
    /*=========顶点表============*/
    class VertexNode
    {
    public:
        int data;
        EdgeNode *firstEdge;
        VertexNode()
        {
            firstEdge = NULL;
        }
    };
    /*********自定义比较函数(优先队列使用)************/
    class mycompare
    {
        bool reverse;
    public:
        mycompare(const bool &re = true)
        {
            reverse = re;    
        }
        bool operator() (EdgeNode *a, EdgeNode *b) const
        {
            //从小到大排列, 优先队列,!mycompare,按照cost的从小到大排列
            if(reverse) return (a->cost > b->cost); 
            else {
                return (a->cost < b->cost);
                //从小到大排列, 优先队列,!mycompare,按照cost的从大到小排列
            }
    
        }
    
    };
    /*********无向图的数据结构*************/
    class Graph 
    {
    public:
    /*********初始化图的邻接表数据***************/
        Graph()
        {
            ifstream fin("pp.txt");
            string line;
            stringstream stream;
            if(getline(fin, line))
            {
                stream.clear();
                stream << line;
                stream >> numVertexes;
                stream >> numEdges;
            }
            init_adjList();
            while(getline(fin, line))
            {
                int vertex, adjacent,  _cost;
                stream.clear();
                stream << line;
                stream >> vertex;
                stream >> adjacent;
                stream >> _cost;
                addEdge(vertex, adjacent, _cost);            
            }
        }
    /********初始化邻接表的顶点表*******/
        void init_adjList()
        {
            adjList.resize(numVertexes);
            for(int i = 0; i < numVertexes; i++)
            {    
                adjList[i].data = i;
            }        
        }
    
    
    /************加边,头插法*****************/
        void addEdge(int a, int b, int _cost)
        {
            EdgeNode *enode1 = new EdgeNode(a-1, b-1, _cost, NULL);
            EdgeNode *enode2 = new EdgeNode(b-1, a-1, _cost, NULL);
            adjList[a-1].data = a-1;
            enode1->next = adjList[a-1].firstEdge;
            adjList[a-1].firstEdge = enode1;
            adjList[b-1].data = b-1;
            enode2->next = adjList[b-1].firstEdge;
            adjList[b-1].firstEdge = enode2;
        }
    /************打印看结果************/
        void print()
        {
            ofstream fout;
            fout.open("primoutput.txt");
            for(int i = 0; i < numVertexes; i++)
            {
                fout << "vertex:" << adjList[i].data << " adj:" ;
                EdgeNode *tmp = new EdgeNode(0, 0, 0 );
                tmp = adjList[i].firstEdge;
                while(tmp)
                {
                    fout << tmp->adjvex << "cost: " << tmp->cost << " ";
                    tmp = tmp->next;
                }
                fout << endl;
            }
        }
    /*********************************/
    public:
        int numVertexes; //顶点数目
        int numEdges;     //边数目
        vector<VertexNode> adjList;   //图的邻接表
    };
    /***********prim算法实现**********/
    class Prims
    {
    public:
        Prims(Graph graph)
        {
            int s = 0;
            length = graph.numVertexes; //顶点数目
            tree.resize(length); 
            marked.push_back(s); //将初始顶点加入最小生成树中
            pq.push(graph.adjList[s].firstEdge); //将初始顶点的第一条边加入队列
            while(!pq.empty())
            {
                EdgeNode *p = new EdgeNode(0,0,0);
                p = graph.adjList[s].firstEdge;
                while(p)
                {
                    if(!is_marked(p->adjvex))
                    {
                        pq.push(p);
                    }
                    p = p->next;
                }
    
                EdgeNode *p1 = new EdgeNode(0,0,0);
                p1 = pq.top();
                pq.pop();
                s = p1->adjvex;
                if(!is_marked(s)) //如果没有加入进最小生成树
                {
                    marked.push_back(p1->adjvex);
                    tree[p1->head].push_back(p1->adjvex); //将边加入最小生成数
                    sum += p1->cost;  //cost的累加
                }
            
            }
    
        }
    /*******************判断是否加入最小生成树***************/    
        bool is_marked(int a)
        {
        
            for(int i = 0; i < marked.size(); i++)
            {
                if(marked[i] == a)
                {
                    return true;
                }
            }
            return false;
        }
    /***************输出看结果**************/
        void write()
        {
            ofstream fout;
            fout.open("tree.txt");
            for(int i = 0; i < length; i++)
            {
                fout << "tree[" << i << "]: " ;
                for(int j = 0; j < tree[i].size(); j++)
                {
                    fout << tree[i][j] << " ";
                }
                fout << endl;
            }
        }
    
    
    public:
        int length;
        int sum = 0;
        vector<int> marked;//最小生成树木的顶点表
        vector<vector<int> > tree; //最小生成树的边 ,数组存储
        priority_queue<EdgeNode*, vector<EdgeNode*>, mycompare> pq; //优先队列
    };
    
    
    int main()
    {
        Graph graph;
        graph.print();
        Prims _prims(graph);
        _prims.write();
        cout << "sum: " << _prims.sum << endl;
        return 0;
    }
    The Safest Way to Get what you Want is to Try and Deserve What you Want.
  • 相关阅读:
    JWT
    JS中try catch的用法
    React高级
    React基础
    获取当前时间前面的时间
    nodeJs
    数组里的字符串数字与数字互转
    寒假学习(二)spark学习
    寒假学习(一)Web开发人员学习路线图
    如何使用GitHub上传本地项目(idea功能强大可直接提交)
  • 原文地址:https://www.cnblogs.com/Shinered/p/9092369.html
Copyright © 2011-2022 走看看