P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles P1048 [NOIP2005 普及组] 采药

P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles

题目描述

观察下面的数字金字塔。

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

        7 
      3   8 
    8   1   0 
  2   7   4   4 
4   5   2   6   5 

在上面的样例中,从 7→3→8→7→57→3→8→7→5 的路径产生了最大

输入格式

第一个行一个正整数 r ,表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

输出格式

单独的一行,包含那个可能得到的最大的和。

输入输出样例

输入 #1

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5 

输出 #1

30

代码

递推式,B站老师讲的超级好!!用前驱数组和备份数组记录和判断路径情况便于输出。

#include<iostream>
using namespace std;
//逆推法输出路径
int main()
{
    int n;
    int i,j; 
    cin >> n;
    int a[n][n];
    for(i=0;i<n;i++)
    {
        for(j=0;j<=i;j++)
            cin >> a[i][j];
    }
    for(i=n-2;i>=0;i--)
    {
        for(j=0;j<=i;j++)
            a[i][j]+=max(a[i+1][j],a[i+1][j+1]);
    }
    cout << a[0][0];
    return 0;
}

拓展:可以输出路径

#include<iostream>
using namespace std;
int main()
{
    int n;
    cin >> n;
    int a[n][n],i,j;
    int b[n][n],p[n][n]; //备份数组b,路径数组p;
    for(i=0;i<n;i++)
    {
        for(j=0;j<=i;j++)
        {
            cin >> a[i][j];
            b[i][j]=a[i][j];
        }
    }
    //逆推数塔
    for(i=n-2;i>=0;i--)
    {
        for(j=0;j<=i;j++)
        {
            if(a[i+1][j]>a[i+1][j+1])
            {
                a[i][j]+=a[i+1][j];
                p[i][j]=0; //路径向下
            }
            else if(a[i+1][j+1]>a[i+1][j])
            {
                a[i][j]+=a[i+1][j+1];
                p[i][j]=1;  //路径向右下
            }
        }
    }
    cout << a[0][0] << endl;
    for(i=0,j=0;i<n-1;i++)
    {
        cout << b[i][j] << "->";
        j+=p[i][j]; //下一行的列数
    }
    cout << b[n-1][j];
    return 0;
}

P1048 [NOIP2005 普及组] 采药 

题目描述

辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”

如果你是辰辰,你能完成这个任务吗?

输入格式

第一行有 2个整数 T和 M,用一个空格隔开,T 代表总共能够用来采药的时间,M 代表山洞里的草药的数目。

接下来的 M 行每行包括两个在 11 到 100 之间的整数,分别表示采摘某株草药的时间和这株草药的价值。

输入输出样例

输入 #1

70 3
71 100
69 1
1 2

输出 #1

3

输出格式

输出在规定的时间内可以采到的草药的最大总价值。

思路+代码

经典的01背包问题,学习了闫式DP的方法,用的二维数组(简化为一维数组的方法还没明白)

#include<iostream>
using namespace std;
const int N=1010;
int t,m; // t:采药时间,m:草药数目
int v[N],w[N];
int f[N][N];
int main()
{
    cin >> t >> m;
    for(int i=1;i<=m;i++)  cin >> v[i] >> w[i] ;
    for(int i=1;i<=m;i++)
    {
        for(int j=0;j<=t;j++)
        {
            f[i][j]=f[i-1][j];
            if(j>=v[i])
                f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
        }
    }
    cout << f[m][t] << endl;
    return 0;
}

(笔记之后总结吧!)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值