2月6日刷题总结

文章介绍了两个问题的解决方案,一个是寻找数字金字塔中路径和最大的路径,另一个是在有限时间内采药以获得最大价值。两种问题都使用了动态规划的方法,通过迭代更新状态以找到最优解。
摘要由CSDN通过智能技术生成

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

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

## 题目描述

观察下面的数字金字塔。

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

```cpp

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

```

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

## 输入格式

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

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

## 输出格式

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

## 样例 #1

### 样例输入 #1

```

5

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

```

### 样例输出 #1

```

30

```

## 提示

【数据范围】

对于 $100\%$ 的数据,$1\le r \le 1000$,所有输入在 $[0,100]$ 范围内。

题目翻译来自NOCOW。

USACO Training Section 1.5

IOI1994 Day1T1

dp过程图解:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int max(int x,int y)
{
    return x>y?x:y;
}
int main()
{
    int r,a[1005][1005]={0};
    scanf("%d",&r);
    //输入
    for(int i=1;i<=r;i++)
    {
        for(int j=1;j<=i;j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
    //dp过程
    for(int i=r-1;i>=1;i--)//从倒数第二行开始
    {
        for(int j=1;j<=i;j++)//遍历这一行的元素
        {
            a[i][j]+=max(a[i+1][j],a[i+1][j+1]);//dp(观看图解理解该式子)
        }
    }
    printf("%d",a[1][1]);
}

P1048 [NOIP2005 普及组] 采药

# [NOIP2005 普及组] 采药

## 题目描述

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

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

## 输入格式

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

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

## 输出格式

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

## 样例 #1

### 样例输入 #1

```

70 3

71 100

69 1

1 2

```

### 样例输出 #1

```

3

```

## 提示

**【数据范围】**

- 对于 $30\%$ 的数据,$M \le 10$;

- 对于全部的数据,$M \le 100$。

**【题目来源】**

NOIP 2005 普及组第三题

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
struct node
{
    int t,v;//时间//价值
}a[105];
int max_(int x,int y)
{
    return x>y?x:y;
}
int main()
{
    int T,M,dp[105][1005]={0};
    scanf("%d%d",&T,&M);
    for(int i=1;i<=M;i++)
    {
        scanf("%d%d",&a[i].t,&a[i].v);
    }
    for(int i=1;i<=M;i++)//种类的遍历
    {
        for(int j=1;j<=T;j++)//时间渐渐自增
        {
            if(j<a[i].t)//当时间不可以满足当前种类的时间的时候
            {
                dp[i][j]=dp[i-1][j];//赋值为上个
            }
            else 
            {
                dp[i][j]=max_(dp[i-1][j],dp[i-1][j-a[i].t]+a[i].v);//取最大
            }
        }
    }
    printf("%d",dp[M][T]);
}

P1616 疯狂的采药

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
typedef long long ll;
ll max_(ll x,ll y)
{
    return x>y?x:y;
}
struct node
{
    ll t;
    ll v;
}a[10005];//用于储存时间和价值
ll dp[10005*10005];//dp数组
int main()
{
    int t,m,v,time;
    scanf("%d%d",&t,&m);//时间和种类的输入
    for(int i=1;i<=m;i++)
    {  //时间和价值的录入
        scanf("%d%d",&time,&v);
        a[i].t=time;
        a[i].v=v;
    }
    //dp过程
    for(int i=1;i<=m;i++)//种类的遍历
    {
        for(int j=a[i].t;j<=t;j++)//从当前种类所需时间开始时间的渐增
        {
            dp[j]=max_(dp[j],dp[j-a[i].t]+a[i].v);
        }
    }
    printf("%lld",dp[t]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡卡卡卡罗特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值