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.
  • 相关阅读:
    HDU 1102 Constructing Roads
    HDU 1285 确定比赛名次。
    最小生成树 HDU 各种畅通工程的题,prim和kru的模板题
    HDU Jungle Roads 1301 最小生成树、
    并查集小结(转)
    HDU hdu 2094 产生冠军 拓扑排序 判定环
    模运算(转)
    拓扑排序(主要是确定环和加法) HDU 2647 Reward
    HDU 1372 Knight Moves 简单BFS
    用计算机模型浅析人与人之间沟通方式 (一)如何谈话
  • 原文地址:https://www.cnblogs.com/Shinered/p/9092369.html
Copyright © 2011-2022 走看看