背包问题详解带例题C++版
背包问题详解C++版.md
背包问题原理具体解析:dd大牛的《背包九讲》
1、01背包问题
题目:有$N$件物品和一个容量为$V$的背包,第$i$件物品的容量是$cost[i]$,价值是$w[i]$,求解将哪些物品放入背包,可以在背包容量允许的情况下,物品价值和最大。
特点:只有一个背包,每个物品只有一个。
函数:$f[i][j] $表示将前$i$件物品放入容量为$j$的背包中时,物品的最大价值。
状态转移方程:
$$
f[i][j] = max(f[i-1][j],f[i-1][j-cost[i]]+w[i])
$$
在空间上将二维转化为一维:
$$
f[j] = max(f[j],f[j-cost[i]]+w[i])
$$
代码:
12345678vector<int>dp(V+1,0);for(int i = 0;i<N;i++){ //循环是从后往前的 for(int j = V;j>=cost[i];j--){ dp[j] = max(dp[j],dp[j-cost[i]]+w[i]); } ...
C++中vector容器使用
C++中vector容器使用.md
1、vector的创建
直接创建一个空vector
1vector<int>temp;
创建一个初始长度为10和初始值为0的vector
1vector<int>temp(10,0);
从原有数组创建vector
12int a[5]={1,2,3,4,5};vector<int>v(a,a+5);
创建二维数组
注意空格
1vector<vector<int> >v;
2、常用函数
取得数组大小
1vector.size()
排序
12sort(vector.begin(),vector.end())//默认升序sort(vector.begin(),vector.end(),greater<int>());//降序
添加元素,会改变数组的大小
1vector.push_back()
删除元素,会改变数组的大小
1vector.pop_back()
清空整个数组
1vector.clear()
交换
123vector ...
十大经典排序算法C++版
十大经典排序算法C++版
对排序的一些术语进行说明。
稳定:如果在原数组中,a在b之前且a=b,排序后a也要在b之前。
不稳定:如果子啊原数组中国,a在b之前且a=b,排序后a可能会出现在b之后。
内排序:所有的排序操作都在内存中完成。
外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
时间复杂度: 一个算法执行所耗费的时间。
空间复杂度:运行完一个程序所需内存的大小。
具体原理:超详细十大经典排序算法总结
1、冒泡排序
两两比较,将大数逐渐交换到数列到最后方。
123456789101112131415vector<int> bubble_sort(vector<int>array){ int n = array.size(); for (int i = 0; i < n; i++) { for (int j = 0; j < n-i-1; j++) { if(array[j]>array[j+1])& ...
c++纯虚函数与抽象基类
c++面向对象编程的思想之一是可以使用继承。继承中一个重要的思想是使用抽象基类(abstract base class,ABC)。
假设我们开发一个程序,需要使用椭圆和圆两种图形。因为圆是椭圆的一种特殊情形,根据继承‘is-a’的思想,自然会想到先定义一个Eclipse类,再将Circle类继承自Eclipse类。
但这样实现有不好的地方。
椭圆中,需要表示长半轴和短半轴、angle(长轴和水平线的夹角),还可以有rotate方法将椭圆进行旋转,这些都是圆所不需要的,将圆继承自椭圆,是十分笨拙的。
一种更好的办法是,使用抽象基类(ABC),将椭圆和圆的共性部分,例如坐标x、y,共同的方法例如移动move、计算面积Area抽象出来放到一个基类shape中,再将Eclipse和Circle类分别继承shape,这样就可以使用基类指针数组同时管理Eclipse和Circle对象。
当类声明中包含纯虚函数时,不能创建该类的对象,此类称为抽象基类。
纯虚函数的声明如下(以Area为例):
1virtual double Area() const =0 ;
ABC类shape的定义如下:
1234 ...
c++重载运算符
运算符的重载使得我们可以更加方便的使用常见的运算符进行操作。
重载运算符的函数格式如下:
1operatorop(argement-list)
接下来的例子中,我们将定义一个Time类,并通过重载运算符+和<<来实现时间的加法和输出显示,其中会使用友元函数(friend)
time.h
1234567891011121314#ifndef TIME_H#define TIME_H#include <iostream>class Time{ private: int minute; int hour; public: Time(); Time(int h=0,int m=0); Time operator+(const Time & t)const; //重载运算符+ friend std::ostream & operator<<(std::ostream & os, const Time & t);//重载运算符<<,使用了友元函数}#end if
ti ...
c++引用变量详解
创建引用变量
引用变量,是已定义变量的别名。
c++中使用&符号来创建引用变量。
例如,将rodents定义为rats的别名,则可以使用以下代码:
12int rats;int & rodents=rats;
此时,rodents和rats指向相同的值和地址。
可以通过下面的代码来测试:
123456789int rats=101;int & rodents=rats;cout<<"rats="<<rats<<",rodents="<<rodents<<endl;rodents++;cout<<"rats="<<rats<<",rodents="<<rodents<<endl;//outputrats=101,rodents=101rats=102,rodents=102
从这方面来说,引用和指针很像,但是有几点不同:
引用必须在声明的时候初始化,而不能先声明,再 ...
c++将函数作为函数参数(函数指针)
如何获取函数的地址
函数名本身就是函数的地址。
假设有一个函数think(),则think就是该函数的地址。
要将函数作为参数进行传递,必须传递函数名。
12process(think); //传递的是函数地址process(think()); //传递的是函数的返回值
声明函数指针
在声明指向函数的指针时,要声明指针指向的函数的类型,即声明应指定函数的返回值类型和参数列表。
假设有一函数,原型如下:double pam(int);
则正确的指针声明如下:double (*pt)(int)
其中,(*pt)是函数,pt是函数指针。
在正确的声明了指针之后,我们就可以将相应的函数的地址赋给它:
pt=pam
使用指针来调用函数
前面指出,(*pt)是函数,与pam作用相同,因此使用的时候直接将它看作函数名即可。
123456double pam(int);double (*pt)(int);pt=pam;double x=pam(10);double y=(*pt)(10);double z=pt(10); //also valid
例子
假设我们需要设计一个名为estimate ...
OpenGL模型加载
是最近学OpenGL的阶段性总结。
学习网址:learnopengl-cn
源码地址:github
对前三节,入门、光照、模型加载的总结。
关于如何使用OpenGL加载一个3D模型并显示在窗口中。
使用OpenGL实现模型加载
初始化GLFW
12345678glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);#ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);#endif
创建GLFW窗口
1234567GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); ...
OpenGL中的VAO与VBO
最近在学习OpenGL的时候,看到了一篇关于讲解VAO和VBO比较好的文章,这里做一下搬运和改良。
原文地址:AB是一家?VAO与VBO
VBO
与其他buffer object一样,VBO归根到底是显卡存储空间里的一块缓存区(Buffer)而已,这个Buffer有它的名字(VBO的ID),OpenGL在GPU的某处记录着这个ID和对应的显存地址(或者地址偏移,类似内存)。用代码看看吧:
123456//生成一个Buffer的ID,不管是什么类型的 glGenBuffers(1, &VBO); //绑定ID,同时也指定该ID对应的buffer的信息类型是GL_ARRAY_BUFFER glBindBuffer(GL_ARRAY_BUFFER, VBO); //为该ID指定一块指定大小的存储区域(区域的位置大抵由末参数影响), 传输数据 glBufferData(GL_ARRAY_BUFFER, sizeof(Data), Data, GL_STATIC_DRAW);
这里是VBO的初始化阶段。在这里我们看到了这是对位置,还是颜色,还是纹理坐标,还是法线 ...
OpenGL之GLAD初始化
GLAD初始化
在GLAD初始化时,会用到下面的语句:
12345if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; }
并且在我的代码中,如果这段初始化代码的位置放置有问题,run的时候就直接输出Fail to initialize GLAD。
如果按照下面的顺序放置,就会fail
1234567if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; }glfwMakeContextCurren ...