标签:http io ar os sp for 数据 on art
题目传送门 http://poj.org/problem?id=1664
设$dp[i][j]$表示$i$个苹果放在$j$个盘子里的总数
$1.$ 当 苹果数 小于 盘子数 $(M < N)$的时候,剩下的$N-M$个盘子都为空,问题等价于在$M$个盘子里放苹果:$$dp[M][N]=dp[M][M]$$
$2.$ 当苹果数 大于等于盘子数$(M \geq N)$的时候,其可以分解为全部盘子都至少放一个苹果$(dp[M-N][N])$和至少有一个盘子为空$(dp[M][N-1])$的两个子结果的合并: $$dp[M][N]=dp[M-N][N] + dp[M][N-1]$$
$3.$递归出口:
$dp[M][1] = 1 ;\\ dp[0][N] = 1$
注意这里,为什么不采用$M=1$呢?只剩一个果子,也是只有一种放法啊。但是,例如,若$dp[3][3] = dp[3][2] + dp[0][3]$,此时$M$为$0$,未收敛于出口$M=1$处,找不到数据。
/*********************************
Author: jusonalien
Email : jusonalien@qq.com
school: South China Normal University
Origin: POJ
*********************************/
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <string>
#include <set>
#include <queue>
using namespace std;
int dp(int m,int n) { //递归版本
if(m==0||n==1) return 1;
if(m < n) return dp(m,m);
else return (dp(m-n,n) + dp(m,n-1));
}
int DP[15][15];
void solve() { //递推版本
for(int i = 0;i <= 12;++i) DP[0][i] = 1;
for(int i = 0;i <= 12;++i) DP[i][1] = 1;
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 main(){
int m,n,t;
solve();
scanf("%d",&t);
while(t--) {
scanf("%d%d",&m,&n);
printf("%d\n",DP[m][n]);
// printf("%d\n",dp(m,n));
}
return 0;
}
标签:http io ar os sp for 数据 on art
原文地址:http://www.cnblogs.com/jusonalien/p/4083209.html