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

NYOJ571

时间:2014-11-24 20:26:31      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   os   sp   for   on   

题目连接:http://acm.nyist.net/JudgeOnline/problem.php?pid=571

这是一道经典题目,是一道将正整数划分成不同情况的题,首先看第一问,首先我们先新建一个数组dp[i][j]表示把i分解成j最大的个数,可以分为两种情况,分解的数里面有j和分解的里面没有j,有j的时候为dp[i-j][j] ,没有j的时候为dp[i][j-1],所以dp[i][j] = dp[i-j][j] + dp[i][j-1],状态转移方程就出来了,这样也能求出来第三小问了。

第二小问:还用dp这个数组只不过上次用完之后这次需要初始化一次,然后我们再来找状态转移方程,dp[i][j]表示将i分解成j个数的个数,这也分为两种情况,分解里面有1和分解里面没有1,有一的时候为dp[i-1][j-1],没有1的时候为dp[i-j][j]    意思是把每份都分一个1。所以可得状态转移方程,dp[i][j] = dp[i-j][j] + dp[i-1][j-1];

第四小问:奇数和dp[i][j]为划分最大的奇数不超过j的数,则dp[i][j]=dp[i-n(j)][j]+dp[i][j-2];n(j)为不超过j的最大奇数,初始条件,dp[i][1]=1,j为偶数时候dp[i][j]=dp[i][j-1];当i==n(j) ,出现dp[0][j],也就是当i为奇数时候,dp[0][j]=1;

第五小问:不同正整数和,dp[i][j]是不超过j的不同的整数和,dp[i][j]=dp[i-j][j-1]+dp[i][j-1];初始状态dp[1][1]=1, 当i==j时,出现dp[0][j-1],表示先拿出一个j出来,这时候就应该是1中情况。

下面看代码:

/*对于输入的 n,k;
第一行: 将n划分成若干正整数之和的划分数。
第二行: 将n划分成k个正整数之和的划分数。
第三行: 将n划分成最大数不超过k的划分数。
第四行: 将n划分成若干个 奇正整数之和的划分数。
第五行: 将n划分成若干不同整数之和的划分数。
第六行: 打印一个空行*/
#include<iostream>
#include <cstring>
#include<vector>
#include <cstdio>
using namespace std;
#define N 55+1
int dp[N][N];

int main()
{
    //分为若干个正整数和
    //memset(dp,0,sizeof(dp));
    int n,k;
    int out[6];
    while(cin>>n>>k)
    {
        memset(dp,0,sizeof(dp));
        //任意个正整数和,则dp[i][j]表示i分解成最大不超过j的个数,
        //分为最大是j和最大不是j,则dp[i][j]=dp[i-j][j]+dp[i][j-1];
        dp[0][0]=1;
        for (int i=0;i<=n;i++)
        {
            for (int j=1;j<=n;j++)
            {
                if(j<=i)
                dp[i][j]=dp[i-j][j]+dp[i][j-1];
                else
                dp[i][j]=dp[i][i];
            }
        }
        out[1]=dp[n][n];
        out[3]=dp[n][k];
        //分成K个正整数的和 ,分为k个数中没有1,和有1,
        //dp[i][j],将i划分为j个dp[i][j]=dp[i-j][j]+dp[i-1][j-1];
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        for (int j=1;j<=i;j++)
        {
              if(j==1)
              dp[i][j]=1;
              else
              dp[i][j]=dp[i-j][j]+dp[i-1][j-1];
        }
        out[2]=dp[n][k];
       //奇数和dp[i][j]为划分最大的奇数不超过j的数,
       //则dp[i][j]=dp[i-n(j)][j]+dp[i][j-2];n(j)为不超过j的最大奇数
       //初始条件,dp[i][1]=1,j为偶数时候dp[i][j]=dp[i][j-1];当i==n(j) ,
       //出现dp[0][j],也就是当i为奇数时候,dp[0][j]=1;
       memset(dp,0,sizeof(dp));
       for(int i=0;i<=n;i++)
       {
           dp[i][1]=1;
           if(i&1)
           dp[0][i]=1;
        }
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=n;j++)
            {
                if(j&1)
                {
                    if(j<=i)
                    dp[i][j]=dp[i-j][j]+dp[i][j-1];
                    else
                    dp[i][j]=dp[i][i];
                }
                else
                dp[i][j]=dp[i][j-1];
            }
        }
        out[4]=dp[n][n];
//不同正整数和,dp[i][j]是不超过j的不同的整数和,dp[i][j]=dp[i-j][j-1]+dp[i][j-1];初始状态dp[1][1]=1;
//当i==j时,出现dp[0][j-1],表示先拿出一个j出来,这时候就应该是1中情况。

        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for (int i=0;i<=n;i++)
        {
              for (int j=1;j<=n;j++)
              {
                   if(j<=i)
                   dp[i][j]=dp[i-j][j-1]+dp[i][j-1];
                    else
                    dp[i][j]=dp[i][i];
              }
        }
        out[5]=dp[n][n];
        for (int i=1;i<=5;i++)
        {
            cout<<out[i]<<endl;
        }
        cout<<endl;

       }
}

 

NYOJ571

标签:style   blog   http   io   color   os   sp   for   on   

原文地址:http://www.cnblogs.com/zhanyage110/p/4119361.html

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