poj1664 放苹果(DPorDFS)&&系列突破(整数划分)

poj1664放苹果

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 33661   Accepted: 20824

Description

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

Input

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

Output

对输入的每组数据M和N,用一行输出相应的K。

Sample Input

1
7 3

Sample Output

8

关键在于找到放的递推关系,要达到不重不露才可!递推关系就是,对于将n个苹果放在m个盘子里,因为可以有空盘子,所以会出现两种情况:一:没空盘子出现;二:有空盘子出现对于一显然每个盘子都至少含有一个苹果,所以此时dp[n][m]=dp[n-m][m];对于二,dp[n][m]=dp[n][m-1];最后注意dp数组的初始化

之所以二考虑了所有情况:假设将5个果子放入3个盘子,在j==2时就已经考虑过了一个盘子是空的情况,所以j==3时考虑一个空盘子的情况也包含了两个都是空的情况

#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m,i,j,k,dp[105][105];
int t;memset(dp,0,sizeof(dp));

for(i=0;i<=100;++i) dp[0][i]=1;
for(i=1;i<=100;++i)
for(j=1;j<=100;++j)
dp[i][j]=dp[i][j-1]+dp[i-j][j];
cin>>t;
while(t--){
cin>>n>>m;
cout<<dp[n][m]<<endl;
}

return 0;
}

递归姿势:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int solve(int n,int m)
{
if(n == 1 || m == 1 || n == 0)
return 1;
if(n<m)
return solve(n,n);
else
return solve(n,m-1)+solve(n-m,m);
}

int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
printf("%d\n",solve(n,m));
}

return 0;
}

由此题引出相似题目,整数划分,求一个整数可以被划分为多少种不同的整数的和

例如:
 如n==6的整数划分为(要求所有的数都小于n)
    
    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种。

仔细想想和放苹果类似,只不过是将n个果子放入n个盘子里!

#include<bits/stdc++.h>
using namespace std;
int solve(int n,int m)
{
if(n==0||m==1||n==1) return 1;
if(n>=m)
return solve(n-m,m)+solve(n,m-1);
else return solve(n,m-1);
}
int main()
{
int n,m;
while(cin>>n) cout<<solve(n,n)<<endl;
return 0;
}

将正整数划分成连续的正整数之和
如15可以划分成4种连续整数相加的形式:
15
7 8
4 5 6
1 2 3 4 5

首先考虑一般的形式,设n为被划分的正整数,x为划分后最小的整数,如果n有一种划分,那么
结果就是x,如果有两种划分,就是x和x x + 1, 如果有m种划分,就是 x 、x x + 1 、 x x + 1 x + 2 、... 、x x + 1 x + 2 ... x + m - 1
将每一个结果相加得到一个公式(i * x + i * (i - 1) / 2) = n,i为当前划分后相加的正整数个数。
满足条件的划分就是使x为正整数的所有情况。
如上例,当i = 1时,即划分成一个正整数时,x = 15, 当i = 2时, x = 7。
当x = 3时,x = 4, 当x = 4时,4/9,不是正整数,因此,15不可能划分成4个正整数相加。
当x = 5时,x = 1。

这里还有一个问题,这个i的最大值是多少?不过有一点可以肯定,它一定比n小。我们可以做一个假设,
假设n可以拆成最小值为1的划分,如上例中的1 2 3 4 5。这是n的最大数目的划分。如果不满足这个假设,
那么 i 一定比这个划分中的正整数个数小。因此可以得到这样一个公式i * (i + 1) / 2 <= n,即当i满足
这个公式时n才可能被划分。

综合上述,源程序如下

int split1(int n)
{
    int i, j, m = 0, x, t1, t2;
   // 在这里i + 1之所以变为i - 1,是因为i * (i - 1) / 2这个式子在下面多次用到,
  // 为了避免重复计算,因此将这个值计算完后保存在t1中。并且将<= 号变为了<号。
    for(i = 1; (t1 = i * (i - 1) / 2) < n; i++) 
    {
        t2 = (n - t1);
        x =  t2 / i;
        if(x <= 0) break;
        if((n - t1) % i == 0)
        {
            printf("%d ", x);
            for(j = 1; j < i; j++)
                printf("%d ", x + j);
            printf("\n");
            m++;
        }
    }
    return m;
}

时间: 2024-10-08 10:17:14

poj1664 放苹果(DPorDFS)&&系列突破(整数划分)的相关文章

poj1664 放苹果(递归)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://poj.org/problem?id=1664 Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第一行是测试数据的数目t(0 <= t <= 20).以下每行均包含二个整数M和N,以空格分开.1<=M,N<=10. Out

POJ1664——放苹果

放苹果 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26595   Accepted: 16906 Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第一行是测试数据的数目t(0 <= t <= 20).以下每行均包含二个整数M和N,以空格分开.1<=M,N<=10. Output 对

POJ1664 放苹果

#include <iostream> #include <cstdio> #include <cstring> using namespace std; int T,n,m; int solve(int m,int n){//m个苹果 n个盘子 if(m<=1||n<=1) return 1;//边界条件 if(m<n) return solve(m,m);//苹果比盘子少 等价于把m个苹果放入m个盘子的方案数 else return solve(m

8787:数的划分(又是一个放苹果)

8787:数的划分 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5: 1,5,1: 5,1,1: 问有多少种不同的分法. 输出:一个整数,即不同的分法. 输入 两个整数n,k (6 < n <= 200,2 <= k <= 6),中间用单个空格隔开. 输出 一个整数,即不同的分法. 样例输入 7 3 样例输出 4

放苹果系列

苹果是否相同(n个苹果) 袋子是否相同(m个袋子) 答案 是 是  DP(详见放苹果) 是 否   否 是  m^n/m! 否 否  m^n

算法笔记——整数划分3

题目来源:POJ1664-放苹果 和POJ3014 问题描述: 把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. 输入: 第一行是测试数据的数目t(0 <= t <= 20).以下每行均包含二个整数m和n,以空格分开.1<=m,n<=10. 输出: 对输入的每组数据m和n,用一行输出相应的K. 分析: 问题描述转换成整数划分形式:把一个正整数m分成至多n个正整数的和,有多少种分法? 假设用f(m,

算法笔记——整数划分2

题目来源:NYOJ176 问题描述: 把一个正整数m分成n个正整数的和,有多少种分法? 例:把5分成3个正正数的和,有两种分法: 1 1 3 1 2 2 输入: 第一行是一个整数T表示共有T组测试数据(T<=50) 每组测试数据都是两个正整数m,n,其中(1<=n<=m<=100),分别表示要拆分的正数和拆分的正整数的个数. 输出: 输出每组拆分的方法的数目. 分析: 题目可以换种等价描述:把m个同样的苹果放在n个同样的盘子里,不允许有的盘子空着不放,问共有多少种不同的分法,其中n

暴力放苹果

放苹果 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27339   Accepted: 17355 Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第一行是测试数据的数目t(0 <= t <= 20).以下每行均包含二个整数M和N,以空格分开.1<=M,N<=10. Output 对

洛谷 P2386 放苹果

P2386 放苹果 题目背景 (poj1664) 题目描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分发(5,1,1和1,1,5是同一种方法) 输入输出格式 输入格式: 第一行是测试数据的数目t(0 <= t <= 20),以下每行均包括二个整数M和N,以空格分开.1<=M,N<=10 输出格式: 对输入的每组数据M和N,用一行输出相应的K. 输入输出样例 输入样例#1: 复制 1 7 3 输出样例#1: 复制 8 输入样例#2: 复制 1 7