01背包问题
背包问题是用来介绍动态规划算法最经典的例子。
https://blog.csdn.net/qq_38410730/article/details/81667885
题目描述:
假设山洞里共有a,b,c,d ,e这5件宝物(不是5种宝物),它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包, 怎么装背包,可以才能带走最多的财富。
首先要理解他的状态转移方程
V[i,j] =V[i-1,j] j<W(i)
V[i,j] =max{V[i-1,j] , V[i-1,j-W(i)] +Pi } j>=W(i)
V[i,j]表示当前背包容量 j,前 i 个物品最佳组合对应的价值。
Pi表示第i个物品的价值,Wi表示第i个物品的体积。
这个状态转移方程就是要做决策:为了价值最大化,第i个物品要放到背包中么?
从理解的角度来说,这个方程的意思是:
当放入第i个物品时:
1、首先判断第i物品放不放的下,通过判断j是否大于第i物品的重量W(i)
如果放不下j<W(i),那么价值不变;
2、如果放得下j>=W(i),那么就在放入这个物品的价值加上剩余背包容量的价值 和 不放入该物品的 价值中选最大值。
从作用的角度来说,这个方程是用来填表的。将已经查找过得子问题答案记录下来。
填V[i,j]二维表,i是有多少个物品,j是有多大容量,填完表结果也就出来了,物品数一般不会太多,但是j的容量太大,二维表建立的就很大,这是一个问题。
贪心算法
题目1
一个数组有 N 个元素,求连续子数组的最大和。 例如:[-1,2,1],和最大的连续子数组为[2,1],其和为 3.
#include <iostream>
#include<climits>
using namespace std;
int main(){
int n,curSum=0,maxSum=INT_MIN;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
{
cin>>arr[i];
curSum+=arr[i];
if(curSum>maxSum)
maxSum=curSum;
if(curSum<0)
curSum=0;
}
cout<<maxSum<<endl;
return 0;
}
动态规划
#include<iostream>
using namespace std;
void findpath(int v[][9],int p[],int w[],int num,int capa,int path[])
{
int i=num;
int j=capa;
int temp;
while(i>0)
{
if(v[i][j]==v[i-1][j])
path[i--]=0;
else
{
path[i]=1;
j=j-w[i];
i--;
}
}
}
int main()
{
int number=4, capacity=8;
int w[5]={0,2,3,4,5}; //重量
int p[5]={0,3,4,5,6}; //价值
int v[5][9]={0}; //动态规划表
int path[5]={0}; //用来保存是否装入背包
for(int i=1;i<=number;i++)
for(int j=1;j<=capacity;j++)
{
if(j<w[i])
v[i][j]=v[i-1][j];
else
v[i][j]=max(v[i-1][j],v[i-1][j-w[i]]+p[i]);
}
cout<<v[number][capacity]<<endl;
findpath(v,p,w,number,capacity,path);
cout<<path[1]<<path[2]<<path[3]<<path[4]<<endl;
}
表格填完,最优解就是v[number][capacity];
//二维数组
#include<iostream>
using namespace std;
long dp[1001][1001];
int main()
{
int n,sum,p[1000]={0};
cin>>n>>sum;
for(int i=1;i<=n;i++)
cin>>p[i];
for(int i=0;i<=n;i++)
dp[i][0]=1;
for(int j=1;j<sum;j++)
dp[0][j]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=sum;j++)
{
if(j<p[i])
dp[i][j]=dp[i-1][j];
else
dp[i][j]=dp[i-1][j]+dp[i-1][j-p[i]];
}
cout<<dp[n][sum]<<endl;
return 0;
}
//一维数组的方法
#include<iostream>
using namespace std;
long dp[1001];
int main()
{
int n,sum,p[1000]={0};
cin>>n>>sum;
for(int i=1;i<=n;i++)
cin>>p[i];
dp[0]=1;
for(int j=1;j<sum;j++)
dp[j]=0;
for(int i=1;i<=n;i++)
for(int j=sum;j>=p[i];j--)
{
dp[j]=dp[j]+dp[j-p[i]];
}
cout<<dp[sum]<<endl;
return 0;
}