本来是做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; }