zhxのDP讲

时间:2021-07-17
本文章向大家介绍zhxのDP讲,主要包括zhxのDP讲使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

DP基础例题

1. 斐波那契数列

f[1]=1;//第0项和第1项
f[0]=0;

//记忆化搜索
int dp(int n)//斐波那契数列第n项
{
//g[i]表示f[i]有没有计算过
if(n<=1)return n;
if(g[n])return f[n];
g[n]=true;
f[n]=dp(n-1)+dp(n-2);
return f[n];//O(fn)
}


//其它求当前
for(int i=2;i<=a;i++)
	f[i]=f[i-1]+f[i-2];
//O(n)


//当前求其它
for(int i=0;i<=n;i++)
{
//O(n)
f[i+1]+=f[i];
f[i+2]+=f[i];
}

2. 组合数

for (int i=0;i<=n;i++)
{
	C[i][0] = 1;//处理边界
	for (int j=1;j<=i;j++)
		C[i][j] = C[i-1][j-1] + C[i-1][j];
}
  1. IOI数字三角形及其系列

状态:f[位][置]=经过的数字之和

f[i][j]:走到 (i,j) 的数字最大和

  1. 滑雪

//滑雪
n行m列
可以走任意四个方向
每走一步需要使得脚底数字变大
最多走几个格子

f[x][y]代表走到(x,y)的最长长度
若:a[x-1][y]>a[x][y];
f[x-1][y]=max(f[x-1][y],f[x][y]+1)
//不正确解,使用自己求其他
//但没有保证当前的位置求出
cin  >> n >> m;
for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
		cin >> a[i][j];

for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
		f[i][j]=1;

for (int x=1;x<=n;x++)
	for (int y=1;y<=m;y++)
		for (int d=上下左右)
		{
			int xx = x朝着d走;
			int yy = y朝着d走;

			if ( (xx,yy)存在 && a[xx][yy] > a[x][y]) f[xx][yy] = max(f[xx][yy],f[x][y]+1); 
		}
  1. 最长上升子序列

个人笔记

  1. 乌龟棋
DP三要素:
  1. 状态
  2. 转移方程
  3. 边界条件

DP可加维度

f[i][j](二维)—f[i][j][k](三维)—f[i][j][k][l](四维)

若时间空间过高,削减冗余状态,减少维度
建一个和原来状态相同的数组储存方案或方案数

有n*m的方格图

背包模型

背包DP

01背包


n个物品 背包容积为m 

第i个物品体积为vi,价值为wi

需要向背包里装一定的物品,在体积不超限的情况下装价值最高的物品

f[编号][体积]=价值

f[i][j]表示考虑完前i个物品 背包已经使用了j的体积

//01背包
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>v[i]>>w[i];
}
//v体积 w价值

for(int i=1;i<=n;i++)
	for(int j=0;j<=m;j++)
	{
		//考虑求f[i][j]
		f[i][j]=f[i-1][j];//第i个物品不选
		if(j>=v[i])		
			f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i])
	}

例题采药

无穷背包

n种物品 背包容积为m
每种物品数量不限
第i个物品体积为vi,价值为wi
f[i][j]表示考虑完前i种类物品 背包已经使用了j的体积

//无穷背包

cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>v[i]>>w[i];
}
//v体积 w价值

for(int i=1;i<=n;i++)
	for(int j=0;j<=m;j++)
	{
		//考虑求f[i][j]
		f[i][j]=f[i-1][j];//第i个物品不选
		if(j>=v[i])		
			f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i])
	}
例题疯狂的采药

有限背包(多重背包)

有N种物品和一个容量为T的背包,第i种物品最多有M[i]件可用,价值为P[i],体积为V[i]

求解:选哪些物品放入背包,可以使得这些物品的价值最大,并且体积总和不超过背包容量。

//有限(多重)背包
cin>>n>>m;

int k=0;
//v体积 w价值 u个数 
for(int i=1;i<=n;i++)
{
int v_,w_,x_;
cin>>v_>>w_>>x_;
int r=1;
while(x_>=r)
{
	k++;
	v[k]=v_*r;
	w[k]=w_*r;
	x_-=r;
	r*=2;
}
if(x_!=0){
k++;
v[k]=v_*x_;
w[k]=w_*x_;

}

}

for(int i=1;i<=n;i++) 
	for(int j=0;j<=m;j++) 
		for(int k=0;k*v[i]<=j&&k<=u[i];k++){
			//考虑如何求f[i][j] 
    f[i][j]=max(f[i][j],f[i-1][j-kv[i]]+k*w[i]);
}

原文地址:https://www.cnblogs.com/DAIANZE/p/15024698.html