aya
一个OIer的水平,基本上是他做dp的好坏来衡量的,那今天来讲一下dp
前导知识点:递归,地推,搜索(深搜就够了),记忆化搜索
先从最简单的问题说起:
[USACO1.5][IOI1994]数字三角形 Number Triangles - 洛谷https://www.luogu.com.cn/problem/P1216这道题先从dfs打起:
#include<stdio.h>
int a[1009][1009];
int max(int a, int b){return a > b ? a : b;}
int dfs(int down, int num)
{
if(down > n || num > down)return;
int ret = 0;
ret = max(dfs(i + 1, num), dfs(i + 1, num + 1)) + a[down][num];
return ret;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= i;j ++)
scanf("%d", &a[i][j];
printf("%d", dfs(1, 1));
return 0;
}
好的,dfs打完你就完成一半了
这时候又把它转成记忆化:
#include<stdio.h>
int a[1009][1009];
int dp[1009][1009];
int max(int a, int b){return a > b ? a : b;}
int dfs(int down, int num)
{
if(dp[down][num])return a[down][num];
if(down > n || num > down)return;
dp[down][num] = max(dfs(i + 1, num), dfs(i + 1, num + 1)) + a[down][num];
return dp[down][num];
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= i;j ++)
scanf("%d", &a[i][j];
printf("%d", dfs(1, 1));
return 0;
}
这时候再给它转成dp:
#include<stdio.h>
int a[1009][1009];
int dp[1009][1009];
int max(int a, int b){return a > b ? a : b;}
int main()
{
int n;
scanf("%d", &n);
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= i;j ++)
scanf("%d", &a[i][j];
for (int i = n;i >= 1;i --)
for (int j = 1;j <= i;j ++)
dp[i][j] = max(dp[i + 1][j] + dp[i + 1][j + 1]) + a[i][j];
printf("%d", dp[1][1]);
return 0;
}
这就很明显了,dp就是一个套路,先dfs,再记忆化,最后地推(dp),题就做出来了(当然还是得多练)