POJ1664
View Code
1 #include<cstdio> 2 #include<cstdlib> 3 #define N 12 4 int f[N][N]; 5 6 int init(int m,int n){ 7 int i,j; 8 if(m==1||n==1)return 1; 9 else if(m==n) return init(m,n-1)+1; 10 else if(m<n) return init(m,m); 11 else if(m>n) return init(m,n-1)+init(m-n,n); 12 } 13 14 int main(){ 15 int t,m,n,i,j; 16 scanf("%d",&t); 17 while(t--){ 18 scanf("%d%d",&m,&n); 19 printf("%d\n",init(m,n)); 20 } 21 return 0; 22 }
递归1:
设f(m,n)为 m 个苹果,n 个盘子的方法数目,
如果 n>m,必定有 n-m 个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响;即 if ( n>m ) ,f ( m ,n )=f( m , m)。
当 n<=m 时,不同的放法可以分成两类:即有至少一个盘子空着或者所有盘子都有苹果,前一种情况相当于 f ( m , n )=f ( m , n-1 );
后一种情况可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即 f ( m , n )=f ( m-n , n )。总的放苹果的放法数目等于两者的和,
即 f ( m , n )=f ( m , n-1 )+f ( m-n , n )。
View Code
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #define N 12 5 int f[N][N]; 6 7 int init(int m,int n){ 8 int i,j; 9 if(f[m][n]!=0)return f[m][n]; 10 else if(m==n) f[m][n]=init(m,n-1)+1; 11 else if(m<n) f[m][n]=init(m,m); 12 else if(m>n) f[m][n]=init(m,n-1)+init(m-n,n); 13 return f[m][n]; 14 } 15 16 int main(){ 17 int t,m,n,i,j; 18 scanf("%d",&t); 19 while(t--){ 20 scanf("%d%d",&m,&n); 21 memset(f,0,sizeof(f)); 22 for(i=0;i<N;i++){ 23 f[i][1]=f[1][i]=1; 24 } 25 init(m,n); 26 printf("%d\n",f[m][n]); 27 } 28 return 0; 29 }
递归2:
利用的f数组记录。减少了一点内存的使用。
keep moving...