【洛谷】训练场_递推与递归二分场(不全)
分析:
与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 即可
(这里就不证明了,网上有很多大牛的解释)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
下一题:
P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles
分析:
R最大是1000,那二维数组可以开出来,想到之前刚学会的回溯,这样就可以遍历所有情况再输出最大值就OK。
没错,以上是TLE的思路。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
然后瞄了一眼题解——还真是以前做过的题呀!
DP算法,从下往上算。
比如例子倒数第1行与倒数第二行
2 7 4 4
4 5 2 6 5
从倒数第二行开始,只需比较4, 5谁大,谁大和2相加并保存。
以此从下往上堆砌,最后得到的第一层即是最大值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }