贪心算法刷题笔记(C++)

贪心算法刷题笔记(C++),第1张

文章目录
  • 前言
  • 会议安排
  • 拼凑字符串
  • Hulfman编码
  • N皇后问题
  • 总结

前言

本帖主要是记录在LeetCode刷题笔记,持续更新中。

会议安排
    // 1.会议室安排,输入为每个会议的起止时间,会议有冲突,要求尽可能多的会议。

struct Agent{ Agent(){ name = "invalid"; start = 0; end = 0; } Agent(std::string a, int b, int c){ name = a; start = b; end = c; } std::string name; float start; float end; bool operator<(const Agent& b) const{ return this->end < b.end; } }; std::vector<Agent> BestAgentArrange(std::vector<Agent> agents, float start){ std::sort(agents.begin(), agents.end());// 按照结束时间的早晚排序 std::vector<Agent> res; for(auto ele : agents){ if(ele.start > start){ res.push_back(ele); start += ele.end; //上一会议的结束时间作为开始时间 } } return res; }

拼凑字符串
// 2.拼凑字符串使得字典数最小
    struct MyCompareDict{
        bool operator()(std::string& lhs, std::string& rhs){
            return lhs + rhs < rhs + lhs;
        }
    };
    
    std::string MinDictMerge(std::vector<std::string> ss){
        std::string res;
        sort(ss.begin(), ss.end(), MyCompareDict());
        for(auto ele : ss){
            res += ele;
        }
        return res;
    }
Hulfman编码
    // 3.Hulfman编码 要求list分割黄金,使得分割成本最低
    int HulfmanCode(const std::vector<int>& list){
        int res = 0;
        int cur = 0;
        std::priority_queue<int> temp(list.begin(),list.end());
        while(temp.size() > 1){
            cur = temp.top();
            temp.pop();
            cur += temp.top();
            temp.pop();
            res += cur;
        }
        return res;

    }
N皇后问题
  • 描述:

N*N网格中放N个皇后,要求每二个皇后不在同一行同一列同一斜线。

返回摆法的数量。

  • 解法:

暴力递归,深度优先,递归探讨每一行,探讨(for)该行的所有valid列,放过皇后的列记录下来,继续往下一行递归,所要种类数,记录所有该行该列的种类数,累加返回就是该行的种类总数。

边界条件,就是顺利完n行的返回1(一种摆法)。

/**
 * @file queen.cpp
 * @author Stephen Ding (1103037805@qq.com)
 * @brief 
 * @version 0.1
 * @date 2022-04-17
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include 
#include 
using namespace std;
class NQueen{
    public:
        int NQueenMethod(int n = 0){
            // n 表示 N个皇后,N*N网格
            if(n < 1) return 0;
            int record[n]; // i : 0 ~ n-1 表示第i行,存储的数值j表示在该行的第j列放一个皇后
            return Process(0, record, n); // 从第0行开始,逐行处理
        }

        /**
         * @brief 
         * 
         * @param i 来到第i行
         * @param record 从上一行正确摆完后传过来的记录,即 0 ~ i-1 已经摆好了,剩下 i ~ n - 1 没有摆
         * @param n 定值
         * @return int 告诉上一行 你这种摆法,从我这一行(i)到下面 i ~ n - 1 能正确摆多少种方法
         */
        int Process(int i, int record[], int n){
            if(i == n) return 1; // 边界条件,能够走通所有的行,即到达终止行,即是一种摆法
            
            int res  = 0;
            
            // 遍历我这一行的所有的列,可以放一个皇后的列都进去,往下面去寻找多少种摆法,总和就是返回值
            for(int j = 0; j < n; ++j){
                if(isValid(record, i, j)){
                    // 第j列可以放
                    // 尝试在该列放,那么能有多少种摆法呢
                    record[i] = j;
                    int temp = Process(i+1, record, n);
                    // 累加
                    res = res + temp; 
                }
            }
            return res;   
        }

        
        bool isValid(int record[], int i, int j){
                // 只要确定 当前行i,在第j列摆放一个皇后,会不会和其他行的数值比较是否 同列 或者 同斜线
                for(int k = 0; k < i; ++k){
                    if(record[k] == j || abs(i - k) == abs(j - record[k])){
                        return false;
                    }
                }
                return true;
            }


};

int main (int argc, char** argv){
    NQueen test;
    int res = test.NQueenMethod(8);// res == 92;
    cout << res << endl;
}
总结

局部最优->全局最优,代码都很短。

解题技巧:
1,举例全排列,暴力解法,即写一个对数器,
2,脑补几个贪心算法,用1验证,
3,不要纠结算法推导,证明较难,费时间。

局部最优并保证传递性(数学归纳法),最后对算法的结果后验:假设法。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/674571.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-19
下一篇2022-04-19

发表评论

登录后才能评论

评论列表(0条)

    保存