2022.02.22 母牛的故事(数组迭代||递归)
题目与思路复盘
题目复盘
题目描述
有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
输入
输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0<n<55),n的含义如题目中描述。
n=0表示输入数据的结束,不做处理。
输出
对于每个测试实例,输出在第n年的时候母牛的数量。
每个输出占一行。
样例输入
2
4
5
0
样例输出
2
4
6
思路复盘
函数如上,类似于斐波那契数列。
首先就想用递归。
#include<iostream>
using namespace std;
int f(int n)
{
if(1<=n && n<=3) return n;
else return f(n-1)+f(n-3);
}
int main()
{
int n;
while(scanf("%d",&n) && n)
printf("%d\n",f(n));
return 0;
}
但只通过了一半的数据。
思考
为什么会超时呢?仔细回头看到题目,发现题目要求多次输入,并且给了一个范围提示,那么是不是可以用一个数组来存储所有的答案,最后用数组下标访问输出答案呢?
那么此处就使用DP,数组的迭代思想。
#include<iostream>
using namespace std;
int ans[56]={0,1,2,3};
int main()
{
int n;
for(int i=4;i<=55;i++) ans[i]=ans[i-1]+ans[i-3];
while(scanf("%d",&n) && n)
printf("%d\n",ans[n]);
return 0;
}
看来,递归有时也不是最优解。
随手一道练习
既然提到了DP,顺手写一道比较简单的DP题
题目来自洛谷P1216
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的样例中,从 7 \to 3 \to 8 \to 7 \to 57→3→8→7→5 的路径产生了最大
输入格式
第一个行一个正整数 rr ,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
输出格式
单独的一行,包含那个可能得到的最大的和。
输入输出样例
输入 #1复制
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出 #1复制
30
说明/提示
【数据范围】
对于 100%100% 的数据,1\le r \le 10001≤r≤1000,所有输入在 [0,100][0,100] 范围内。
题目翻译来自NOCOW。
USACO Training Section 1.5
IOI1994 Day1T1
把DP表达式推出来即可
a[i][j]+=max(a[i-1][j-1],a[i-1][j]);
我的AC代码如下...
#include <iostream>
using namespace std;
int r;
int a[1005][1005];
void slove()
{
a[2][1]+=a[1][1];
a[2][2]+=a[1][1];
for(int i=3;i<=r;i++)
{
for(int j=1;j<=i;j++)
{
a[i][j]+=max(a[i-1][j-1],a[i-1][j]);
}
}
int max=-1;
for(int j=1;j<=r;j++)
{
if(a[r][j]>max) max=a[r][j];
}
printf("%d\n",max);
}
int main()
{
cin>>r;
for(int i=1;i<=r;i++)
for(int j=1;j<=i;j++)
cin>>a[i][j];
slove();
return 0;
}
害,又是水了的一天.///....
end...关注后续跟新~~