码迷,mamicode.com
首页 > 其他好文 > 详细

POJ1664 计数 DP

时间:2014-11-08 14:49:59      阅读:229      评论:0      收藏:0      [点我收藏+]

标签: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;
}

POJ1664 计数 DP

标签:http   io   ar   os   sp   for   数据   on   art   

原文地址:http://www.cnblogs.com/jusonalien/p/4083209.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!