m个物品放n个盒子,盒子物品都相同,问你放的方法总数是多少
看着像个排列组合,算着算着就发现我排列组合都忘得差不多啦,哎,什么时候能打败遗忘呢
然后想用dp做,但是转移的方面没有想好
看了看题解感觉这个思路太符合逻辑了
递归和非递归的都差不多,非递归的初值要赋好,递归的呢只要赋值好所有可能的结束条件就好了
对于i个放j个中如果j比i大是不是就会有j-i个盘子是空的,那么和把 i 放 i个的结果是一样的
然后如果i >= j 呢,是不是就有两种情况1、至少有一个盘子是空的——>dp[i][j-1]
第二种情况没有空的,那是不是从每个盘子里拿出来一个对结果没有影响呢——》dp[i-j][j]
所以dp[i][j] = dp[i][j-1] + dp[i - j][ j]
#include <iostream> #include <cstdio> #include <algorithm> #include <string.h> using namespace std; const int maxn = 20; int dp[maxn][maxn];//i个苹果放j个盘子 int q_pow(int a,int b) { int ret = 1; while(b) { if(b & 1)ret *= a; b >>= 1; a *= a; } return ret; } int main() { for(int i = 1;i <= 10;i++) { dp[1][i] = 1; dp[i][1] = 1; dp[0][i] = 1; dp[i][0] = 0;//谁能退到这样的状态dp[1][1] = dp[0][1] + dp[1][0] } for(int i = 1;i <= 10;i++) { for(int j = 1;j <= 10;j++) { if(i < j)dp[i][j] = dp[i][i]; else { dp[i][j] = dp[i - j][j] + dp[i][j-1]; } } } int m,n,t; cin >> t; while(t--) { cin>>m>>n; cout<<dp[m][n]<<endl; } return 0; }