标签:
Description:m个苹果放n个盘子,盘子可以为空,1,1,5和5,1,1为同一种放法。
哦--原来是计数问题。遇到计数问题像我这种蒟蒻一般用两种方法来处理:
1. 数学公式【Mathmatics rules the world!!!!!
2. dp【动态规划千秋万代一统江湖
哦。这道题公式归纳好像不大好弄。。那就dp吧QAQ实际上dp就是数学递推QAQ;
想一想怎么表示状态。。。f[i][j]表示什么呢= =
(以下是一个蒟蒻的心理活动。由于蒟蒻十分脑残并不能一眼看出状态)
每个苹果都是一模一样的 盘子也是一模一样的没有区分。
这个时候状态代表的意义不应该是第几个苹果 || 第几个盘子如何如何。。【。。。由于前面写了几道dp状态大概都是这样所以惯性就想到这个。。】
和问题相关的量实际上只有盘子的‘数量’ && 苹果的‘数量’。。所以状态应该表达的是:
f[i][j] = i个苹果放置在j个盘子里的方案数。
下面考虑i和j在不同数量关系下的转换方程。。
当苹果数>=盘子数时(i >= j ) 我们有两种选择,也就是有两种状态对当前状态的解做了贡献:
1.挥霍掉所有的盘子。此时就相当于。先一个盘子放一个苹果。之后我们再考虑剩下的苹果如何放到j个盘子里。此时问题就转化成f[i - j][j]了;
2. 傲娇的扔掉几个盘子不用。也就是至少空着一个盘子;
所以方程可以写成 f[i][j] = f[i][j - 1] + f[i - j][j]
当苹果数<盘子数时(i < j) 盘子一定是放不满的。有j - i个盘子肯定是不用的是多出来的,此时问题的解就转化为f[i][i]时问题的解;
所以完整的方程就是:
f[i][j] = f[i][j - 1] + f[i - j][j] <-- ( i >= j )
f[i][j] = f[i][i] <-- ( i < j )
然后我们考虑初始化。若盘子只有一个或没有的时候 || 苹果只有一个或没有的时候算入答案里的方案一定只有一个。所以把i== 1||0, j == 1||0 的f[i][j]都设为0;
由于循环顺序的缘故所以我们可以在循环中赋值, 不用先赋。
1 #include <iostream>
2 #include <string.h>
3 #include <math.h>
4 #include <algorithm>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #define ll long long
8
9 using namespace std;
10 int n, m, c, f[20][20];
11 int main()
12 {
13 scanf("%d", &c);
14 while(c --){
15 scanf("%d%d", &n, &m);
16 memset(f, 0, sizeof(f));
17 for(int i = 0; i <= n; i ++){
18 for(int j = 0; j <= m; j ++){
19 if(i == 1 || !i || !j || j == 1) f[i][j] = 1;
20 else if(i >= j) f[i][j] = f[i - j][j] + f[i][j - 1];
21 else if(i < j) f[i][j] = f[i][i];
22 }
23 }
24 printf("%d\n", f[n][m]);
25 }
26 return 0;
27 }
NAILED IT..
-----------------------------
怎么办好害怕过几天就测试了可是窝还是这么弱TATATATATATATATAT
标签:
原文地址:http://www.cnblogs.com/shadyqwq-juruo/p/5720654.html