😊😊 😊😊
不求点赞,只求耐心看完,指出您的疑惑和写的不好的地方,谢谢您。本人会及时更正感谢。希望看完后能帮助您理解算法的本质
😊😊 😊😊
题目描述:
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
Input
输入的是一行是一个整数N (1 < N <= 100),给出三角形的行数。下面的N行给出数字三角形。数字三角形上的数的范围都在0和100之间。
Output
输出最大的和。
Sample Input
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
Sample Output
30
小白到进阶各种解法:
一、暴搜:😊
代码:
写法一:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 5e2 + 10;
int f[N][N]; //表示矩阵
int n;
int res;
void dfs (int x, int y, int cost)
{
if (x == n)
{
res = max(res, cost);
return ;
}
dfs (x+1, y, cost + f[x+1][y]);
dfs (x+1, y+1, cost+f[x+1][y+1]);
}
int main()
{
cin >> n;
for (int i=1; i <= n; i ++)
for (int j=1; j <= i; j ++)
cin >> f[i][j];
dfs(1, 1, f[1][1]);
cout << res << endl;
return 0;
}
写法二:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 5e2 + 10;
int f[N][N]; //表示矩阵
int n;
int dfs (int x, int y)
{
if (x == n)
return f[x][y];
int res=f[x][y]; //记录从当前状态到目的状态的最优答案
res += max(dfs (x+1, y), dfs (x+1, y+1));
return res;
}
int main()
{
cin >> n;
for (int i=1; i <= n; i ++)
for (int j=1; j <= i; j ++)
cin >> f[i][j];
cout << dfs(1, 1) << endl;
return 0;
}
二、记忆化搜索:😊
代码:
被卡了一个数据!
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 5e2 + 10, inf = 11010;
int mm[N][N];
int g[N][N];
int n;
int dfs (int x, int y)
{
if (mm[x][y])
return mm[x][y];
if (x == n){
mm[x][y] = g[x][y];
return mm[x][y];
}
int res=0;
res += max(dfs(x+1, y), dfs(x+1, y+1)) + g[x][y];
mm[x][y] = res;
return res;
}
int main()
{
cin >> n;
for (int i=1; i <= n; i ++)
for (int j=1; j <= i; j ++)
cin >> g[i][j];
cout << dfs (1, 1);
return 0;
}
还是被卡了一个数据:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 5e2 + 10, inf = 11010;
int mm[N][N];
int g[N][N];
int n;
int dfs (int x, int y)
{
if (mm[x][y])
return mm[x][y];
if (x == n){
mm[x][y] = g[x][y];
return mm[x][y];
}
mm[x][y] += max(dfs(x+1, y), dfs(x+1, y+1)) + g[x][y];
return mm[x][y];
}
int main()
{
cin >> n;
for (int i=1; i <= n; i ++)
for (int j=1; j <= i; j ++)
cin >> g[i][j];
cout << dfs (1, 1);
return 0;
}
三、本题考察算法:动态规划😊
代码:
正推写法:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 5e2 + 10, inf = 0x3f3f3f3f;
int g[N][N];
int f[N][N];
int n;
int main()
{
scanf("%d", &n);
int a;
for (int i=1; i <= n; i ++)
for (int j = 1; j <= i; j ++ )
{
cin >> g[i][j];
}
memset (f, -inf, sizeof(f));
f[1][1] = g[1][1];
for (int i=2; i <= n; i ++)
{
for (int j=1; j <= i; j ++)
{
f[i][j] = max(f[i-1][j], f[i-1][j-1]) + g[i][j];
}
}
int res=-inf;
for (int i=1; i <= n; i ++)
res = max(res, f[n][i]);
cout << res;
return 0;
}
倒推写法:无需初始化
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 5e2 + 10, inf = 11010;
int f[N][N];
int g[N][N];
int n;
int main()
{
cin >> n;
for (int i=1; i <= n; i ++)
for (int j=1; j <= i; j ++)
cin >> g[i][j];
for (int i=n; i >= 1; i--){
for (int j=1; j <= i; j ++){
f[i][j] = max(f[i+1][j], f[i+1][j+1]) + g[i][j];
}
}
cout << f[1][1];
return 0;
}