NYOJ 18 The Triangle(基础dp)

 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值