zoukankan      html  css  js  c++  java
  • 笔试题总结:贪心算法(或动态规划)

    概念:

    当一个问题具有最优子结构性质时,可用动态规划算法,有时会有更简单有效的算法,那就是贪心算法,贪心算法是通过一系列的选择来得到问题的解,贪心算法并不从整体最优上加以考虑,所做的选择只是在某种意义上的局部最优解。但对范围相当广的许多问题能产生整体最优解。在一些情况下,即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好的近似解。

    贪心算法的基本要素:

    贪心选择性质:所求解的问题的整体最优解可以通过一系列局部最优的选择来,即贪心选择达到。贪心选择所依赖的是以前所做过的选择,而对以后所做的选择没有关系。

    最优子结构性质:一个问题的最优解包含其子问题的最优解。

    贪心算法与动态规划的区别:

    动态规划是通过自底向上的方式解决子问题,贪心算法是通过自顶向下的迭代方式做出贪心选择,求解问题的最优解。两共同点是都具有最优子结构性质。

    动态规划:(0-1)背包问题

    https://blog.csdn.net/qq_38410730/article/details/81667885

    类似:

    1.欢聚时代:容量M,电影N部,每部喜爱值不一样,电影大小不一样,求不超过容量最喜欢的值

    100 5//容量,5部电影

    29 28 19 18 20//电影容量

    9   4     3   8 10//每部喜爱值

    以上是典型 的0-1背包问题,动态规划来解决

    思路:

      weight[N]={29 28 19 18 20} 

      value[N]={9   4     3   8 10}

    容量N=100

    (i) weight(j) value
    0 0 0
    1 29 9
    2 28 4
    3 19
    4 18
    5 20 10

    B(i,j)//意思是,可选第i件商品以前的任意商品,还剩余容量j的最大价值

    B(i,j)---->j(剩余容量)<weight[i](第i件物品的容量,重量),只能选第i-1件以前的,即b(i-1,j)

       ---------->选i, B(i-1,j-values[i])

       ---------》不选i,  B(i-1,j)

    动态规划:创建一个二维数组

    //背包问题
      int dp(vector<int>& value, vector<int>& weight, int cap,int n)
    {
        vector<vector<int>> vvi(n + 1, vector<int>(cap + 1, 0));
        for (int i = 1; i < n + 1;i++)
        {
            for (int j = 1; j < cap + 1;j++)
            {
                if (j < weight[i]) vvi[i][j] = vvi[i - 1][j];
                else
                {
                    int A = vvi[i - 1][j - weight[i]]+value[i];
                    int B = vvi[i - 1][j];
                    vvi[i][j] = max(A,B);
                }
            }
        }
        return vvi[n][cap];
    }
    int main()
    {
        int n, cap;
        int v, w;
        cin >> n >> cap;
        vector<int>value(n+1,0), weght(n+1,0);
        
        for (int i = 1; i < n+1;i++)
        {
            cin >> v;
            value[i]=v;
        }
        for (int i = 1; i < n+1; i++)
        {
            cin >> w;
            weght[i]=w;
        }
        for (auto i:value)
        {
            cout << i << " ";
        }
        cout << endl;
        for (auto i : weght)
        {
            cout << i << " ";
        }
        cout << endl;
        cout << n << cap << endl;
        cout <<dp(value,weght,cap,n)<<endl;
        system("pause");
    }

    下面的解法是错误的

    #include <iostream>
    #include <map>
    #include <vector>
    #include <algorithm>
    #include <functional>
    using namespace std;
    int main()
    {
        int cap,num,tmp;
        map<int, int, greater<int>> love_size;
        cin >> cap>>num;
        cout << cap << ":" << num << endl;
        vector<int> movie, love;
        for (int i = 0; i < num;i++)
        {
            cin >> tmp;
            movie.push_back(tmp);
        }
        for (int i = 0; i < num; i++)
        {
            cin >> tmp;
            love.push_back(tmp);
        }
        for (int i = 0; i < num;i++)
        {
            love_size.insert(make_pair(love[i],movie[i]));
        }
        int love_sum=0;
        int movie_cap = 0;
        for (auto v:love_size)
        {
    
            movie_cap += v.second;
            love_sum += v.first;
            cout << "select:" << v.first << ":" << v.second  <<":"<<love_sum<<endl;
            if (movie_cap >= cap)
            {
                if (movie_cap> cap) love_sum -= v.first;
                break;
            }
    
        }
        cout << love_sum << endl;
        system("pause");
    }
        

    华为:一百块钱需要买100只鸡,公鸡5元一只,母鸡3元一只,小鸡一元三只。请输出所有可能的情况。

    5*x+3*y+z/3=100

    x+y+z=100

    0=<x<=25

    0=<y<=33

    0=<z/3<=100

    #include<iostream.h>
    void main()
    {
        int x,y,z,count=0;
        cout<<"百钱买百鸡的方案有:"<<endl;
        for(x=0;x<=20;x++)
            for(y=0;y<=33;y++)
                for(z=0;z<=300;z=z+3)
                 if(5*x+3*y+z/3==100&&x+y+z==100)
                 {
                     ++count;
                     cout<<count<<":"<<x<<","<<y<<","<<z<<endl;
                 }
                
    }

    类似的比如百度:

     1,2

    N

    可以考虑使用动态规划或者斐波拉数列

    F(N)=F(N-1)+F(N-1) //F表示多少中方法

    n=1 return 1

    n=2  return 2

    return f(n-1)+f(n-2)

    或者

    void step(int n)
    {
        vector<long long> v(n+1, 0);
        if(n>=1) v[1] = 1; 
        if(n>=2) v[2] = 2;
        for (int i = 3; i <= n;i++)
        {
            v[i] = v[i - 1] + v[i - 2];
        }
        cout << v[n] << endl;
    }
    int main()
    {
        step(1);
        step(2);
    
        step(3);
        step(4);
        step(5);
        step(10);
        system("pause");
    }

     //间隔,不能选相邻的数字,使其最优(和最大)

    //1 2 4 1 7 8 3
    //4 1 1 9 3
    //opt[i] = max(opt[i - 2] + vi[i] , opt[i-1]);
    
    int dp_dg(vector<int>& vi,int n)//最后一个元素
    {
    	int A, B;
    	if (n == 0) return vi[0];
    	else if (n == 1) return max(vi[0], vi[1]);
    	else
    	{
    		
    		A = dp_dg(vi, n - 2) + vi[n];
    		B = dp_dg(vi, n - 1);
    		return max(A, B);
    		
    	}
    }
    int dp(vector<int>& vi)//最后一个元素
    {
    	int A, B;
    	vector<int> v_dp(vi.size(),0);
    	v_dp.resize(vi.size());
    	v_dp[0] = vi[0];
    	v_dp[1] = max(vi[1], vi[0]);
    	for (int i = 2; i < vi.size();i++)
    	{
    		A = vi[i] + v_dp[i - 2];
    		B = v_dp[ i - 1];
    		v_dp[i] = max(A,B);
    	}
    	return v_dp[v_dp.size() - 1];
    }
    int main()
    {
    	int num,tmp;
    	cin >> num;
    	vector<int> vi(num);
    	for (int i = 0; i < num;i++)
    	{
    		cin >> tmp;
    		vi.push_back(tmp);
    	}
    
    	cout<<dp(vi)<<endl;
    	system("pause");
    }
    

      

    //3 34 4 12 5 2能否凑出9,能,返回true,否则返回false
    //3 34 4 12 5 2
    //s=9 true
    //subset(i,s)=subset(i-1,s-v[i])
    //subset(i,s)=subset(i-1,s);
    条件:
    //1.i=0,return v[i]==s
    //2,s=0 return true
    //v[i]>s--->subset(i-1,s);
    /*bool subset1(vector<int>& vi, int i,int s)
    {
        int A, B;
        if (i == 0) return vi[0] == s;
        if (s == 0) return true;
        if (vi[i] > s) return subset(vi, i - 1, s);
        A = subset(vi, i - 1, s - vi[i]);
        B = subset(vi, i - 1, s);
        return A || B;
    
    }*/
     bool subset(vector<int>& vi, int s)
    {
        vector<vector<bool>> vvi(vi.size(),vector<bool>(s+1));
        int A, B;
        
        for (int i = 0; i < s + 1;i++)
            vvi[0][i] =false;
        vvi[0][vi[0]] = true;
        for (int i = 0; i < vi.size();i++)
        {
            vvi[i][0] = true;
        }
        for (int i = 1; i < vi.size();i++)
        {
            for (int j = 1; j < s + 1; j++)
            {
                if (vi[i]>j) vvi[i][j] = vvi[i - 1][j];
                else
                {
                    A = vvi[i - 1][j - vi[i]];
                    B = vvi[i - 1][j];
                    vvi[i][j] = A || B;
                }
            }
            
        }
        return vvi[vi.size() - 1][s];
    }
    int main()
    {
        int n,tmp;
        vector<int> vi;
        cin >> n;
        for (int i = 0; i < n;i++)
        {
            cin >> tmp;
            vi.push_back(tmp);
        }
        cout<<boolalpha<<subset(vi,9)<<endl;
        cout << boolalpha << subset(vi, 10) << endl;
        cout << boolalpha << subset(vi, 12) << endl;
        cout << boolalpha << subset(vi, 9) << endl;
        cout << boolalpha << subset(vi, 13) << endl;
        system("pause");
        return 0;
    }
  • 相关阅读:
    【专项学习】—— TypeScript基础语法入门
    【重点突破】—— React应用中封装axios(转)
    【重点突破】—— vue中Axios的封装和API接口的管理(转)
    【后台管理系统】—— 基础功能模块的开发之登录
    【后台管理系统】—— 通用部分的开发
    【后台管理系统】—— 开发环境的搭建之webpack的配置
    【重点突破】—— 三大框架对比Vue&React&Angular
    【大众点评】—— 首页开发
    【大众点评】—— 前端架构设计
    【重点突破】—— React Router 4:全新的React组件式的动态路由库
  • 原文地址:https://www.cnblogs.com/bwbfight/p/11505264.html
Copyright © 2011-2022 走看看