【洛谷】训练场_递推与递归二分场(不全)

P1192 台阶问题

分析:

P1255数楼梯题意一样,只不过数据不一样,数楼梯一题是涉及高精度与字符串处理。

如果数据不大,且每次最多只能迈2级阶梯的话,本题则是斐波那契数列的裸题。

1阶:1

2阶:2

3阶:1阶+2阶(1阶时迈2步,2阶时迈1步)

以次类推;

这题写多了几个K后,我发现了一个新的规律:

当K=4时;

0阶:0

1阶:1(0阶+1)

2阶:2(0阶+1阶+1)

3阶:4(0阶+1阶+2阶+1)

4阶:8(0阶+1阶+2阶+3阶+1)

5阶:16(1阶+2阶+3阶+4阶)因为0阶加不加都无所谓可以去掉

6阶:30(2阶+3阶+4阶+5阶)

以此类推;

思路是一样的,求第4阶的方案数,等于在第1阶上迈3步+在第2阶上迈2步+在第三阶迈1步+直接在底层(0阶)迈4步他们的方案数的总和。

剩下的就是类似斐波那契数列的处理了。

题目要求输出的 ans 要 mod 100003 ,因此我们只要知道 (a + b) % c = [(a%c) + (b%c)] % c 即可

(这里就不证明了,网上有很多大牛的解释)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 const int MOD = 100003;
 7 int N, K;
 8 long long num[102];
 9 int ans;
10 
11 int main()
12 {
13     while(cin >> N >> K){
14         // 类斐波那契数列前的处理
15         ans = 0;
16         memset(num, 0, sizeof(num));
17         num[0] = 0; num[1] = 1; num[2] = 2;
18         for(int i = 3; i <= K; i++){
19             for(int j = 0; j < i; j++){
20                 num[i] += num[j] % MOD;
21             }
22             num[i] %= MOD;
23             num[i] = (num[i]%MOD + 1%MOD) % MOD;
24         }
25         //开始走楼梯
26         for(int i = K+1; i <= N; i++){
27             ans = 0;
28             for(int j = 1; j <= K; j++){
29                 ans += num[j]%MOD;
30                 ans %= MOD;
31                 if(j==K) num[j] = ans;
32                 else num[j] = num[j+1];
33             }
34         }
35         // 注意要比较 N 与 K 的大小比较
36         if(N >= K) cout << num[K] << endl;
37         else cout << num[N] << endl;
38 
39     }
40     return 0;
41 }
AC代码

下一题:

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

分析:

R最大是1000,那二维数组可以开出来,想到之前刚学会的回溯,这样就可以遍历所有情况再输出最大值就OK。

没错,以上是TLE的思路。

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 int R;
 6 int tri[1001][1001];
 7 int ans, tot;
 8 
 9 void down(int a, int b){
10     if(a == R) {
11         tot += tri[a][b];
12         if(tot > ans) ans = tot;
13         return ;
14     }
15     else {
16         tot += tri[a][b];
17         down(a+1, b);
18         tot -= tri[a+1][b];
19         down(a+1, b+1);
20         tot -= tri[a+1][b+1];
21     }
22     return ;
23 }
24 int main()
25 {
26     while(cin >> R){
27         tot = ans = 0;
28        for(int i = 1; i <= R; i++){
29         for(int j = 1; j <= i; j++){
30             cin >> tri[i][j];
31         }
32        }
33 
34        down(1, 1);
35 
36        cout << ans << endl;
37     }
38     return 0;
39 }
5AC4TLE

然后瞄了一眼题解——还真是以前做过的题呀!

DP算法,从下往上算。

比如例子倒数第1行与倒数第二行

  2  7  4  4

4  5  2  6  5

从倒数第二行开始,只需比较4, 5谁大,谁大和2相加并保存。

以此从下往上堆砌,最后得到的第一层即是最大值。

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 
 5 int R;
 6 int ans[1001][1001];
 7 
 8 int main()
 9 {
10     while(cin >> R){
11         for(int i = 1; i <= R; i++)
12         for(int j = 1; j <= i; j++)
13             cin >> ans[i][j];
14 
15         for(int i = R-1; i >= 1; i--)
16         for(int j = 1; j <= i; j++)
17             ans[i][j] += max(ans[i+1][j], ans[i+1][j+1]);
18 
19        cout << ans[1][1] << endl;
20     }
21     return 0;
22 }
AC代码

猜你喜欢

转载自www.cnblogs.com/Ayanowww/p/10852390.html