本来是做DP专题的,但我觉得还是多试试从基础的递推开始训练。可能对Dp有多点帮助。做到最后也发现递推也是很精妙的啊!这些题目来自hdu。都是for beginner~~ 我觉得我还是踏实点的好~~ 继续努力~~
| HDU 2044 | 一只小蜜蜂... |
到 n 分别有两条路,n-1 和 n-2 。
一般这些题要注意用long long 型的,这个让我WA了几次~~
#include <iostream>
using namespace std;
int main()
{
long long dp[51],i,j,n;
dp[1] = 1;
dp[2] = 2;
for(i = 3;i < 51;i ++)
dp[i] = dp[i-1] + dp[i - 2];
while(cin>>n)
{
while(n --)
{
cin>>i>>j;
cout<<dp[j-i]<<endl;
}
}
return 0;
}
| HDU 2045 | 不容易系列之(3)―― LELE的RPG难题 |
想像一下,如果你一开始不知道这题是递推题,我怎么去思考这道题?这题高中时是一种排列组合的题型。
要学会用分情况和假设的思维方式来考虑递推问题。
如果是分情况来看待这题,这题首尾颜色不一样的条件会使情况越分越多,并且可能导致不全面,所以要简化这题。
进行假设,假设首尾颜色可以一样,那么就会豁然开朗。即3*2^(n-1)种。然后要剪除颜色一样的情况,颜色首尾一样就是f(n-1)的情况了。所以结果就是f(n)=3*2^(n-1) - f(n-1);
#include <iostream>
using namespace std;
int main()
{
long long f[51],i,n,cot = 4;
f[1] = 3;f[2] = 6;
for(i = 3;i < 51;i ++)
{
f[i] = 3*cot-f[i-1];
cot*=2;
}
while(cin>>n)
cout<<f[n]<<endl;
return 0;
}
| HDU 2046 | 骨牌铺方格 |
递推题还有一种方法,就是枚举找规律,很明显,这题是Fibonacci。
分情况来分析这道题,因为是加东西上去,那在n-1拍好的情况下+1.只有一种情况,发现还有一些情况没考虑到,在n-2的情况下+2,也只有一种情况,发现所有情况都考虑到了,得到方程。
#include <iostream>
using namespace std;
int main(){
__int64 f[51];
int i,n;
f[0]=1;
f[1]=1;
f[2]=2;
f[3]=3;
for(i=4;i<51;i++){
f[i]=f[i-1]+f[i-2];
}
while(cin>>n){
printf("%I64d\n",f[n]);
}
return 0;
}
| HDU 2047 | 阿牛的EOF牛肉串 |
很明显这道题要分类出来讨论,分为结尾是 O的 f1 和 结尾不是 O的 f2。
结尾不是 O 的种数 : (上一次结尾是 O 的 + 上一次结尾不是 O 的)* 2 ;即是:f2(n+1) = 2 * ( f1(n) + f2(n) ) 。
然后很容易发现结尾是 O 的等于上一次结尾不是 O 的种数。 即 f1(n) = f2(n-1) 。
也就是说:f2(n+1) = 2* ( f2(n-1) + f2(n)); f1(n+1) = f2(n); f1(1) = 1;f2(1) = 2;F(1) = 3; F(2) = 6;
于是 F(n+1) = 2*(F(n-1) + F(n)) ;
#include <iostream>
using namespace std;
int main()
{
long long dp[50],i,n;
dp[1] = 3;dp[2] = 8;
for(i = 3;i < 41;i ++)
{
dp[i] = 2*(dp[i-2] + dp[i-1]);
}
while(cin>>n)
{
cout<<dp[n]<<endl;
}
}
| HDU 2048 | 神、上帝以及老天爷 |
错排,F(n) 表示n 人错排种数。如果把第i 个数放在非原位 k 上,则有n-1种。 此时 k 位的数可有两种情况: 1、放在 i 上,则有 F(n-2) 种。 2、放在非 i 上,则有F(n-1)种。
所以F(n) = (n-1) * (F(n-2) + F(n-1));
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n,m,t,i;
double M[34],N[34];
double ans;
M[1] = 0;
M[2] = 1;
N[0] = 1;N[1] = 1;N[2] = 2;
for(i = 3;i < 34;i ++)
{M[i] = (i-1)*(M[i-1]+M[i-2]);N[i]=i*N[i-1];}
cin>>t;
while(t--)
{
cin>>n;
ans = double(M[n]/N[n]);
//cout<<M[n]<<" "<<N[n]<<endl;
printf("%.2lf%%\n",100*ans);
}
return 0;
}
| HDU 2049 | 不容易系列之(4)――考新郎 |
也是错排。
#include <iostream>
using namespace std;
int main()
{
int n,m,t,i;
long long M[34],N[34];
M[1] = 0;
M[2] = 1;
N[0] = 1;N[1] = 1;N[2] = 2;
for(i = 3;i < 34;i ++)
{M[i] = (i-1)*(M[i-1]+M[i-2]);N[i]=i*N[i-1];}
cin>>t;
while(t--)
{
cin>>n>>m;
cout<<M[m]*(N[n]/N[m]/N[n-m])<<endl;
}
return 0;
}
看来做递推就是找规律,分类,假设,有点创造性思维。
本文通过几个实例展示了递推问题的解决方法,包括使用递推公式、分情况讨论、假设简化等策略。重点讲解了Fibonacci序列的应用,通过不同问题的解析,揭示了递推思想的精妙之处。
199

被折叠的 条评论
为什么被折叠?



