zoukankan      html  css  js  c++  java
  • poj1664(放苹果)

    题目链接:http://poj.org/problem?id=1664

     关于放苹果的那些事。。。。。。。。。。

       今天偶然看到一个关于整数划分的算法, 仔细看了后,我想到了放苹果的事,其实这个问题困扰了我很久,一直没想明白放苹果的原理。记得当时做这个题的时候,自己的分析的方法和整数划分的算法是一样的,就是没想到用递归就能做出来,看了一位dn的博客,终于明白是怎么回事了.........

    例子, 

     整数划分的思想如下:
    整数划分问题是将一个正整数n拆成一组数连加并等于n的形式,且这组数中的最大加数不大于n。
    如6的整数划分为

    6
    5 + 1
    4 + 2, 4 + 1 + 1
    3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
    2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
    1 + 1 + 1 + 1 + 1 + 1

    共11种。下面介绍一种通过递归方法得到一个正整数的划分数。

    递归函数的声明为
    int split(int n, int m);其中n为要划分的正整数,m是划分中的最大加数(当m > n时,最大加数为n),
    1 当n = 1或m = 1时,split的值为1,可根据上例看出,只有一个划分1 或 1 + 1 + 1 + 1 + 1 + 1
    可用程序表示为if(n ==
    1 || m == 1) return 1;

    2 下面看一看m 和 n的关系。它们有三种关系
    (
    1) m > n
    在整数划分中实际上最大加数不能大于n,因此在这种情况可以等价为split(n, n)
    ;
    可用程序表示为if(m > n) return split(n, n);
    (2) m = n
    这种情况可用递归表示为split(n, m -
    1) + 1,从以上例子中可以看出,就是最大加
    数为6和小于6的划分之和
    用程序表示为if(m == n) return (split(n, m -
    1) + 1);
    (3) m < n
    这是最一般的情况,在划分的大多数时都是这种情况。
    从上例可以看出,设m =
    4,那split(6, 4)的值是最大加数小于4划分数和整数2的划分数的和。
    即 split(
    6,4) = split(6,3) + split(2,4)
    因此,split(n, m)可表示为split(n, m -
    1) + split(n - m, m)

           按照整数划分的思想,将一个整数划分为若干(x<=n) 整数,按由大到小逐级递减的顺序排列,  这样保证了不会出现 5,1,1 和 1,5,1 这种想同的情况,根据这样的思路来建立一个递推关系。

    以前用dfs写的代码
    #include"iostream"
    using namespace
    std;
    int count=0;
    int M,m,n;
    void DFS(int k, int s,int t)
    {

    if( s==n ){
    if(t==m) count++
    ;
    return ;
    }
    int i;
    for(i=k;i>=0; i--){
    if( t + i <= m )
    {
    DFS(i, s+
    1, t+i);
    }
    else
    {
    continue
    ;
    }
    }
    }
    int main()
    {

    int i;
    scanf("%d",&M);
    while(M--)
    {
    count=
    0;
    scanf("%d %d",&m, &n);
    for(i=m;i>=0;i--)
    {
    DFS(i,
    1,i);
    }
    printf(
    "%d\n",count);

    }
    return
    0;
     递推法
    #include"iostream"
    using namespace
    std;
    int split(int n, int m)
    {
    if(n==1
    ||m==1) return 1;
    else
    {
    if(m>n)
    {
    return split(n , n)
    ;
    }
    if(m==n) return split(n ,m-
    1)+1;

    if(m<n)
    {
    return split(n , m-
    1)+split(n-m , m);
    }
    }
    }
    int main()
    {
    int t,m,n;
    cin>>t;
    while(t--)
    {
    cin>>m>>n
    ;
    cout<<split(m , n)<<endl;;
    }
    return
    0;
    }
    看来要向别人学习的地方还很多啊。。。。 努力
  • 相关阅读:
    开发者和设计师:为何我们不能好好相处?(转载)
    PHP ACCESS
    来自腾讯的session跨域,跨服代码
    php大括号妙用。
    php mysql 记录集的操作
    开始我的代码笔记
    收藏一个php用的一个页码按钮类
    修改过后的数字英文字符生成图片代码
    搜藏一点php session 常用方法
    php包含漏洞收集程序代码
  • 原文地址:https://www.cnblogs.com/FCWORLD/p/2015312.html
Copyright © 2011-2022 走看看