DP动态规划-打ACM你必须知道的算法
Posted Ja_king_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DP动态规划-打ACM你必须知道的算法相关的知识,希望对你有一定的参考价值。
动态规划
1.什么是动态规划?
动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。解决DP问题,要明确转移和状态两个问题。
这么说大家可能也不知道啥是动态规划,那我们一起看看一些经典例题吧!
2.经典例题1:数字三角形
(1)给你一个数字三角形,从顶点出发,向下或向右下走一步,直至最底层,将途经相加,所得到的最大值。
如上图所示,7开始,可以选择向下或向右下走一步。能得到的最大值便是30。
(2)这题如何解决呢?
定义f[i][j]表示从(1,1)出发走到(i,j)所有路径的最大和。
7
3 8
8 1 0
例如:f[3][2]=max{7+3+1,7+8+1}=16(因为到达(3,2)这点就两条路径)
所以我们便可以直接DP,最后在max(f[n][1]…f[n][n])中找答案即可。
大致过程如图所示。
3.经典例题2:最长上升子序列
(1)题目描述:给你一个数组,删除部分元素得到最长上升子序列
如:1 13 5 7 8 2 11
5
1 5 7 8 11
(2)这题如何解决呢?
f[i]表示以i结尾的上升子序列中的最长长度。
f[j]=max(f[i])+1,a[i]<a[j]
大致如图所示。
读到这里,你是不是觉得很简单,那我们来看看一道比较有难度的题吧
4.经典题目3:过河卒问题
这题看起来是不是有点难度啦?
其实也非常简单,马拦截的地方赋值为0,然后DP,a[i][j]=a[i-1][j]+a[i][j-1]
我们来看看代码实现吧:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int x1[9]={0,-2,-1,1,2,2,1,-1,-2};
const int y1[9]={0,1,2,2,1,-1,-2,-2,-1};
long long s[25][25]={0},a[25][25]={0};
int n,m,x,y;
int main()
{
scanf("%d%d%d%d",&n,&m,&x,&y);
memset(a,0,sizeof(a));
a[x][y]=1;
for(int i=1;i<=8;i++)
if(x+x1[i]>=0&&y+y1[i]>=0)
a[x+x1[i]][y+y1[i]]=1;
//a数组用来标记马的位置,马和马的控制点设为1
s[0][0]=1;
for(int i=1;i<=n;i++)
{
if(a[i][0]==0) s[i][0]=1;
else break;//如果边界有马,后面的就都为0
} //行
for(int j=1;j<=m;j++)
{
if(a[0][j]==0) s[0][j]=1;
else break;
} //列
//设置边界的初值
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(a[i][j]==0)
s[i][j]=s[i-1][j]+s[i][j-1];
//位置没有马就继续累加
else s[i][j]=0;
}
printf("%I64d",s[n][m]);
return 0;
}
这样就过了,这是洛谷的一道题,大家可以去做做哟~
5.这些你都懂了,那就做做01背包问题吧
这也是DP经典问题,大家尝试做做看!
关注我,下期我们来分析01背包问题!!!
以上是关于DP动态规划-打ACM你必须知道的算法的主要内容,如果未能解决你的问题,请参考以下文章