贪心算法(基础)
创始人
2024-05-23 00:04:22
0

目录

一、什么是贪心?

(一)以教室调度问题为例

1. 问题

2. 具体做法如下

3. 因此将在这间教室上如下三堂课 

4. 结论

(二)贪心算法介绍  

1. 贪心算法一般解题步骤

二、最优装载问题

(一)问题 

(二)分析 

(三) 核心代码 

(四)完整代码

三、完全背包问题 

(一)问题 

(二)分析  

(三)举例  

(四)核心代码 

(五)完整代码

(六)物品类的完整代码


一、什么是贪心?

(一)以教室调度问题为例

1. 问题

  • 假设有如下课程表,你希望将尽可能多的课程安排在某一间教室上

  

2. 具体做法如下

  • 第一步:选出结束最早的课,它就是要在这间教室上的第一堂课
  • 第二步:接下来,必须选择第一堂课结束后才开始的课。同样,选择结束最早的课,这将是要在这间教室上的第二堂课 

3. 因此将在这间教室上如下三堂课 

 

4. 结论

  •  这道题就采取的贪心算法===>每步都采取最优的做法

(二)贪心算法介绍  

  • 贪心算法又称贪婪算法,是指在对问题求解时,总是做出当前看来最好的选择,它不是从整体上加以考虑,所做出的仅是在某种意义上的局部最优解。而局部的最优解叠加在一起便是该问题整体的最优解,或者近似最优解。

1. 贪心算法一般解题步骤

  • 将问题分解为若干个子问题
  • 找出合适的贪心策略
  • 求解每一个子问题的最优解
  • 将局部最优解堆叠成全局最优解

二、最优装载问题

(一)问题 

  • 有一艘海盗船,载重量为C,每一件古董的重量为w_{i},海盗们如何尽可能的把多数量的宝贝装上海盗船 ?

(二)分析 

  1. 当载重量为定值的时候,w_{i}越小时,可装载的古董数量n越大,只要依次选择最小重量的古董即可
  2. 把n个古董的重量从小到大(非递减)排序,然后根据贪心策略尽可能多地选出前i个古董,直到不能继续装为止

(三) 核心代码 

template
void Loading(T1 c, vector& w, vector& t, vector& v)
{//冒泡排序for (int i = w.size() - 1; i > 0; i--)//扫描次数{for (int j = 0; j < i; j++){if (w[j] > w[j + 1]){swap(w[j], w[j + 1]);//交换物品重量swap(t[j], t[j + 1]);//交换物品的序号}}}for (int k = 0; w[k] <= c; k++){v[k] = true;c = c - w[k];//船的剩余装载量}
}

(四)完整代码

#include
#include
#include
using namespace std;
template
void Loading(T1 c, vector& w, vector& t, vector& v)
{//冒泡排序for (int i = w.size() - 1; i > 0; i--)//扫描次数{for (int j = 0; j < i; j++){if (w[j] > w[j + 1]){swap(w[j], w[j + 1]);//交换物品重量swap(t[j], t[j + 1]);//交换物品的序号}}}for (int k = 0; w[k] <= c; k++){v[k] = true;c = c - w[k];//船的剩余装载量}
}
int main()
{float c;//表示船的最大载重和物品个数int n;//物品个数cout << "请依次输入船的最大载重和物品个数:" << endl;cin >> c >> n;vector w(n);//存放物品的重量vector t(n);;//存放物品的下标vector v(n);//记录物品是否装入船中cout << "请依次输入物品重量:" << endl;for (int i = 0; i < n; i++)//初始化物品信息{cin >> w[i];t[i] = i;v[i] = false;}Loading(c,w,t,v);cout << "装入了:" << endl;for (int i = 0; i < w.size(); i++)//输出装入的物品{if (v[i] == true)cout << t[i] << "号物品," << "重量为:" << w[i] << endl;}return 0;
}
//测试数据
//30 8
//4 10.5 7.8 4.9 5.1 3.3 4.6 3.2//结果
//装入了:
//7号物品,重量为:3.2
//5号物品,重量为:3.3
//0号物品,重量为:4
//6号物品,重量为:4.6
//3号物品,重量为:4.9
//4号物品,重量为:5.1

三、完全背包问题 

(一)问题 

  • 有n件物品,每件物品有一定的重量w和相应的价值v,背包的最大容量为bagW,一种物品只能拿一样(不可重复拿),物品可以分割,求解将哪些物品装入背包里物品价值总和最大?

(二)分析  

  • 依照贪心策略,每次选取单位重量价值最大的物品,也就是说每次选择性价比(价值/重量)最高的物品,如果达到运载重量bagW,那么一定能得到价值最大

(三)举例  

 背包最大容量为30,在依次选择物品2、10、6、3、5后,背包最大价值达到69,背包剩余容量为30-(2+5+8+9+5)=1,只能装8号物品的\frac{1}{4},此时背包最大价值为69+\frac{1}{4}\times 6=70.5

(四)核心代码 

void CompletePack(int _bagW,int n,struct goods*ps)
{double sum = 0;//背包总价值for (int i = 0;ips[i].w)//背包容量大于物品重量{ps[i].c = 1;sum =sum+ ps[i].v;_bagW = _bagW - ps[i].w;//剩余背包容量}else//背包容量小于物品重量{ps[i].c = (double)_bagW / (double)ps[i].w;//装入物品的比例(必须要强制转换)sum =sum+ps[i].c *ps[i].v;break;}}cout << "背包最大价值:" << sum << endl;
}

(五)完整代码

#include
#include
#include//setw的头文件
using namespace std;
#define MAX 100//物品数量最多为100
struct goods
{int n;//物品编号int w;//物品重量int v;//物品价值double p;//物品性价比double c;//记录装入物品的比例(如果物品完全放入背包,则c=1;不放入,c=0)
}g[MAX];void Init(int n, struct goods*ps);//初始化物品信息
bool cmp(struct goods a,struct goods b);//比较
void CompletePack(int _bagW,int n,struct goods*ps);
void print(int n, struct goods* ps);//遍历void Init(int n, struct goods*ps)//初始化物品信息
{cout << "请依次输入物品的重量和价值:" << endl;for (int i = 0; i < n; i++){ps[i].n = i;//物品编号cin >>ps[i].w >> ps[i].v;//初始化物品重量和价值ps[i].p = (double)ps[i].v / (double)ps[i].w;//性价比ps[i].c = 0;//都没有放入背包}
}bool cmp(struct goods a,struct goods b)//比较
{return a.p > b.p;//根据物品单位价值从大到小排序
}
void CompletePack(int _bagW,int n,struct goods*ps)
{double sum = 0;//背包总价值for (int i = 0;ips[i].w)//背包容量大于物品重量{ps[i].c = 1;sum =sum+ ps[i].v;_bagW = _bagW - ps[i].w;//剩余背包容量}else//背包容量小于物品重量{ps[i].c = (double)_bagW / (double)ps[i].w;//装入物品的比例(必须要强制转换)sum =sum+ps[i].c *ps[i].v;break;}}cout << "背包最大价值:" << sum << endl;
}
void print(int n, struct goods* ps)
{for (int i = 0; i < n; i++){if (ps[i].c != 0){if (ps[i].c == 1)cout << "物品" << ps[i].n << setw(20) << "价值为:" << ps[i].v << endl;elsecout << "物品" << ps[i].n << "装入了" << ps[i].c <> bagW >> n;Init(n,g);//初始化物品信息cout << endl<

(六)物品类的完整代码

#include
#include //setw的头文件
using namespace std;
#define MAX 20//物品数量最多为20
class goods
{
private:int number;//物品编号int weight;//物品重量double value;//物品价值double percentage;//物品性价比double choice;//记录装入物品的比例(如果物品完全放入背包,则choice=1;不放入,choice=0)
public:goods() { ; }goods(int _n,int _w, double _v, double _p, double _c)//构造函数{this->number = _n;this->weight = _w;this->value = _v;this->percentage = _p;this->choice = _c;}//~goods();//析构函数//获取私有成员int getn();//获取私有成员numberint getw();//获取私有成员weightdouble getv();//获取私有成员valuedouble getp();//获取私有成员percentagedouble getc();//获取私有成员choice//修改私有成员void setn(int _n);//修改私有成员的numbervoid setw(int _w);void setv(double _v);void setp(double _p);void setc(double _c);
};int goods::getn()
{return number;
}
int goods::getw()//获取私有成员weight
{return weight;
}
double goods::getv()
{return value;
}
double goods::getp()
{return percentage;
}
double goods::getc()
{return choice;
}void goods::setn(int _n)
{number = _n;
}
void goods::setw(int _w)
{weight = _w;
}
void goods::setv(double _v)
{value = _v;
}
void goods::setp(double _p)
{percentage = _p;
}
void goods::setc(double _c)
{choice = _c;
}
int main()
{int bagW, n;//背包最大容量和物品数量cout << "请依次输入背包容量和物品数量:" << endl;cin >> bagW >> n;//goods *g=new goods[MAX];goods g[MAX];cout << "请依次输入物品重量和物品价值:" << endl;for (int i = 0; i < n; i++){int _n,_w,_c;//物品编号,物品重量,物品是否放入了背包double _v, _p;//物品价值,物品性价比cin >> _w >> _v;_p = _v / _w;//性价比_n = i;//编号_c = 0;//是否放入了背包goods gg(_n, _w, _v, _p, _c);g[i] = gg;}for (int i = 0; i <= n - 1; i++)//简单选择排序(按照性价比从大到小){double max = g[i].getp();int k = i;//保存最大性价比的物品下标for (int j = i; j < n; j++){if (max < g[j].getp()){max = g[j].getp();k = j;}}swap(g[i], g[k]);}double sum = 0;//背包总价值for (int i = 0; i < n; i++){if (bagW > g[i].getw())//背包容量大于物品重量{g[i].setc(1);//物品全部装入背包sum += g[i].getv();//背包价值增加bagW = bagW - g[i].getw();//剩余背包容量}else//背包容量大于物品重量{double x = double(bagW) / double(g[i].getw());g[i].setc(x) ;//装入物品的比例sum += g[i].getc() * g[i].getv();break;}}cout << "物品的最大价值为:" << sum << endl;for (int i = 0; i < n; i++){if (g[i].getc() != 0){if (g[i].getc() == 1)cout << "物品" << g[i].getn() << setw(20) << "价值为:" << g[i].getv() << endl;elsecout << "物品" << g[i].getn() << "装入了" << g[i].getc() <

相关内容

热门资讯

非安卓10系统手机,探索非安卓... 你有没有想过,为什么有些人会选择非安卓10系统的手机呢?是不是觉得这有点奇怪?别急,今天就来带你一探...
手机图标制作安卓系统,手机图标... 你有没有想过,那些在手机屏幕上跳动的图标,其实都是精心设计出来的艺术品呢?没错,今天就要带你一探究竟...
安卓系统和鸿蒙系统谁大,谁才是... 你有没有想过,手机里的操作系统就像是一场无声的较量?今天,咱们就来聊聊这个话题:安卓系统和鸿蒙系统,...
bj40安卓系统,功能解析与使... 你有没有发现,最近你的BJ40越野车变得聪明多了?没错,它升级了安卓系统,简直就像给它装上了个智能大...
安卓系统硬件核心板,揭秘智能设... 你有没有想过,手机里的安卓系统其实就像是一个庞大的城市,而硬件核心板就是这座城市的核心区域?今天,就...
王者荣耀安卓系统转区ios系统... 你有没有想过,把你的王者荣耀账号从安卓系统转到iOS系统呢?这可不是一件小事,里面可是有大学问的哦!...
安卓系统的音游,节奏与音乐的完... 你有没有发现,手机里的游戏越来越好玩了?尤其是那些音游,简直让人停不下来!今天,就让我带你深入了解一...
安卓系统取消下方按键,探索全新... 你知道吗?最近安卓系统来了一次大变动,那就是取消了下方按键!这可真是让人眼前一亮,让我们一起来看看这...
安卓系统显示原理设置,从像素到... 你有没有发现,你的安卓手机屏幕上那些花花绿绿的图标和文字,其实背后有着一套神奇而又复杂的显示原理呢?...
平板安卓4.0系统下载,平板下... 你有没有想过,拥有一台运行着最新安卓4.0系统的平板电脑,那感觉简直就像拥有了未来的钥匙?想象流畅的...
安卓原生12系统下载,原生系统... 你有没有听说?安卓原生12系统终于来了!这款全新的操作系统,不仅带来了全新的视觉体验,还有一堆实用的...
安卓怎么下泼辣系统,安卓设备轻... 你有没有想过给你的安卓手机来个“大变身”?想象你的手机瞬间变成了一个泼辣的“女侠”,不仅个性十足,而...
安卓版小米系统下载,畅享智能生... 你有没有发现,最近手机圈里又掀起了一股热潮?没错,就是安卓版小米系统的下载。这款系统自从推出以来,就...
提取安卓系统自带软件,探索安卓... 你有没有想过,你的安卓手机里那些看似不起眼的自带软件,其实都是隐藏的宝藏呢?今天,就让我带你一探究竟...
安卓系统投屏到鸿蒙系统,鸿蒙系... 亲爱的读者们,你是否有过这样的体验:手里拿着安卓手机,却想在大屏幕的鸿蒙系统设备上展示内容?别急,今...
sony 电视安卓8.0系统,... 亲爱的读者们,你是否也和我一样,对科技产品有着浓厚的兴趣呢?今天,我要和你聊聊一个让我眼前一亮的话题...
安卓 替换系统下载,探索安卓系... 你有没有想过,你的安卓手机其实可以换换口味呢?没错,就是那个一直默默陪伴你的系统,今天就来带你一起探...
安卓系统证书信任,安卓系统证书... 你有没有遇到过这种情况?手机里突然弹出一个提示,告诉你某个应用需要获取系统证书信任,然后你一脸懵逼,...
安卓系统应用数据目录,揭秘系统... 你有没有想过,你的安卓手机里那些应用,它们的数据都藏在哪个角落呢?今天,就让我带你一探究竟,揭开安卓...
kindle 安卓 系统 刷机... 亲爱的读者们,你是不是也和我一样,对电子阅读设备情有独钟?尤其是那款小巧便携的Kindle,简直是阅...