The Triangle
时间限制:
1000 ms | 内存限制:
65535 KB 难度:
4
-
描述
-
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
(Figure 1)
Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right.
-
输入
- Your program is to read from standard input. The first line contains one integer N: the number of rows in the triangle. The following N lines describe the data of the triangle. The number of rows in the triangle is > 1 but <= 100. The numbers in the triangle, all integers, are between 0 and 99. 输出
- Your program is to write to standard output. The highest sum is written as an integer. 样例输入
-
5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
样例输出
-
30
//dp,n2的算法
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int dp[100+10][100+10];
int main()
{
int n;
while(cin>>n)
{
for(int i=1; i<=n; i++)
for(int j=1; j<=i; j++)
scanf("%d",&dp[i][j]);
for(int i=n-1; i>=1; i--)
{
for(int j=1; j<=i; j++)
{
dp[i][j]+=max(dp[i+1][j],dp[i+1][j+1]);
}
}
printf("%d\n",dp[1][1]);
}
return 0;
}//ac
//递归算法
#include<iostream>
using namespace std;
#define N 1000
int map[N][N];
int n;
int triangle(int x, int y)
{
if (x == n)
{
return map[x][y];
}
int l = triangle(x + 1, y);
int r = triangle(x + 1, y + 1);
return map[x][y] + (l > r ? l : r);
}
int main()
{
while (cin >> n)
{
memset(map, 0, sizeof(map));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
cin >> map[i][j];
printf("%d\n", triangle(1, 1));
}
return 0;
}
//滚动数组算法
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 1000;
int d[MAX][MAX];
int main(int argc, char const *argv[])
{
int n;
while(cin>>n && n) {
for(int i = 1; i <= n; i++)
for(int j = 1; j <= i; j++)
cin>>d[i][j];
int *result = d[n];//骚操作在这里
for(int i = n-1; i >= 1; i--)
for(int j = 1; j <= i; j++)
result[j] = max(result[j],result[j+1]) + d[i][j];
cout << result[1] << endl;
}
return 0;
}
//记忆化搜索
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1000
int map[N][N],vis[N][N];
int n;
int triangle(int x, int y)
{
if (x == n)
return map[x][y];
if (vis[x][y])
return vis[x][y];
vis[x][y] = max(triangle(x + 1, y),
triangle(x + 1, y + 1)) + map[x][y];
return vis[x][y];
}
int main()
{
while (cin >> n)
{
memset(vis, 0, sizeof(vis));
memset(map, 0, sizeof(map));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
cin >> map[i][j];
printf("%d\n", triangle(1, 1));
}
return 0;
}
//dfs
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1000
int map[N][N], vis[N];
int n,Max,s;
void dfs(int x, int y)
{
int i;
if (x == n)
{
Max = max(Max, s);
return;
}
for (int i = 0; i <= 1; i++)
{
s += map[x + 1][i+y];
dfs(x + 1, i+y);
s -= map[x + 1][i+y];
}
}
int main()
{
while (cin >> n)
{
memset(vis, 0, sizeof(vis));
memset(map, 0, sizeof(map));
Max = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
cin >> map[i][j];
s = map[1][1];
dfs(1, 1);
printf("%d\n", Max);
}
return 0;
}
//位运算穷举
/*
我们将从每个节点上向左还是向右选择一个数0或1来表示
则从顶点到底边的一次累加过程,就获得一个n-1位的二进制
于是,我们枚举n-1位的二进制数,就能得到2的n次方个不同的和
取其最大值即可
感觉很多类似二选一的类型题,都可以考虑使用位运算
因为与位运算0 1恰好对应
*/
/*
5
1
2 3
4 5 6
7 8 9 2
1 3 5 7 9
因为b是从0开始的,即对应的是全部都向左下走
枚举每一b的二进制数都对应其走法
用穷举思想即可,因为2的n次方包含了所有走法
*/
#include<iostream>
#include<algorithm>
using namespace std;
#define N 100
int map[N][N];
int n,Max,s,b;
void triangle()
{
int i, j, s = 0;
int t = 1 << (n - 1);
for (i = j = 1; i <= n; i++)
{
if (b&t) //如果b&t的值为1 就是向右
j++;
s += map[i][j];
t = t>> 1; //n>>=1 中的>>=意思是先将变量n的各个二进制位顺序右移1位,
//最高位补二进制0,然后将这个结果再复制给n。
}
Max = max(Max, s);
}
int main()
{
int lim;
while (cin >> n)
{
memset(map, 0, sizeof(map));
Max = 0;
lim = 1 << (n-1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
cin >> map[i][j];
for ( b= 0; b < lim; b++)
triangle();
printf("%d\n",Max);
}
return 0;
}