hdu 1028 Ignatius and the Princess III(dp||母函数)

来源:互联网 发布:淘宝店铺营销计划 编辑:程序博客网 时间:2024/05/09 20:01

小记:一开始自己是用的dp,dp数组定义也对了。但是就是状态转移方程少加一个步。然后看了一下discuss,别人用了dp,更多的是母函数,不过我一开始用的是dp那么就用dp解。然后看了一眼别人的dp,发现和自己定义的是一样的,所以就自己继续想状态转移方程,终于理解出来了。


思路:母函数模板题,我的blog里可看讲解,dp,这里先讲讲dp,

dp[i][j]表示对数i,用不大于j的数组成i的 种数

状态转移方程:

对于i<j,dp[i][j] = dp[i][i]

对于i==j,dp[i][j] = 1 + dp[i][j-1]

对于i>j,dp[i][j] = dp[i-j][j] + dp[i][j-1]

主要的一个方程就是i>j时的。

dp[i][j] 包括两个部分,

第一部分就是不包括j且小于用小于j的数组成i的种数

第二部分就是包括了一个j,那么我们剩下的还要凑齐的就是i-j这个数,而用来凑的数不能大于j,

所以,第一部分的种数就是dp[i-j][j],第二部分的种数即为dp[i][j-1]

例:

  4 = 4;
  4 = 3 + 1;
  4 = 2 + 2;
  4 = 2 + 1 + 1;
  4 = 1 + 1 + 1 + 1;
dp[4][3] = dp[4][2] + dp[1][3]

通过上面理解,dp[i][j]一部分是包括了j的和不包括j的两部分


初始化,dp[0][i] = dp[i][0] = 0

dp[1][i] = dp[i][1] = 1


dp代码:

#include <iostream>#include <cstdio>using namespace std;const int MAX_ = 130;int f[MAX_][MAX_];void init(){    for(int i = 1;i < MAX_;++i){        f[0][i] = 0;        f[i][0] = 0;        f[i][1] = 1;        f[1][i] = 1;    }    for(int i = 1; i < MAX_; ++i){        int cnt = 0;        for(int j = 1; j < MAX_; ++j){            if(i < j)f[i][j] = f[i][i];            else if(i == j)f[i][j] = 1 + f[i][j-1];            else {                f[i][j] = f[i-j][j] + f[i][j-1];            }        }    }}int main(){    //freopen("f:\\out.txt","w",stdout);    long long n;    init();    while(cin>>n){        cout<<f[n][n]<<endl;    }    return 0;}


母函数模板直接提交,直接A,改都不用改:

#include <iostream>using namespace std;// Author: Tanky Woo// www.wutianqi.comconst int _max = 10001;// c1是保存各项质量砝码可以组合的数目// c2是中间量,保存没一次的情况int c1[_max], c2[_max];int main(){//int n,i,j,k;int nNum;   //int i, j, k;while(cin >> nNum){for(i=0; i<=nNum; ++i)   // ---- ①{c1[i] = 1;c2[i] = 0;}for(i=2; i<=nNum; ++i)   // ----- ②{for(j=0; j<=nNum; ++j)   // ----- ③for(k=0; k+j<=nNum; k+=i)  // ---- ④{c2[j+k] += c1[j];}for(j=0; j<=nNum; ++j)     // ---- ⑤{c1[j] = c2[j];c2[j] = 0;}}cout << c1[nNum] << endl;}return 0;}


0 0
原创粉丝点击