标题不允许有666,这什么规定。。。
ybt 1206:放苹果
ybt 1222:放苹果
OpenJudge NOI 2.2 666:放苹果
OpenJudge NOI 2.3 666:放苹果
OpenJudge NOI 2.5 666:放苹果
OpenJudge NOI 2.6 666:放苹果
洛谷 P2386 放苹果
注:ybt 1192页面打不开
a[i][j]
:将i个苹果放入j个盘子的方案数a[i][j] = 1
。a[i][j] = 1
。a[i][j] = 1
。a[i][i]
。a[i][j-1]
a[i-j][j]
做题时,由于有t组询问,可以将其看做t次求解同样的问题。也可以先求出所有可能的状态,而后进行t次询问。
思路与解法1中的类似,递归问题对应递推状态,递归关系对应递推关系,递归出口对应初始状态。
递归问题为:求将i个苹果放入j个盘子的方案数,记作solve(i, j)
递归关系对应递推中的递推关系,递归出口对应递推中的初始状态。将递推的解析中的a[i][j]
都改做solve(i, j)
看即可。
该题不做记忆化也能过,如果做记忆化递归,那么:
记忆状态与递归状态一致,为将i个苹果放入j个盘子的方案数,记作a[i][j]
。
该题等价于:将一个整数M拆分为n个正整数相加的形式(n <= N),问有多少种拆分方式。
拆分过程中要保证后面拆分出来的数字大于等于前面拆分出来的数字(类似求组合数时的做法)这样才能避免统计重复的情况。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t, m, n, a[15][15];
cin >> t;
while(t--)
{
cin >> m >> n;
for(int i = 0; i <= m; ++i)
for(int j = 1; j <= n; ++j)
{
if(i == 0 || i == 1 || j == 1)
a[i][j] = 1;
else if(i < j)
a[i][j] = a[i][i];
else
a[i][j] = a[i][j-1] + a[i-j][j];
}
cout << a[m][n] << endl;
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t, m, n, a[15][15];
cin >> t;
for(int i = 0; i <= 10; ++i)
for(int j = 1; j <= 10; ++j)
{
if(i == 0 || i == 1 || j == 1)
a[i][j] = 1;
else if(i < j)
a[i][j] = a[i][i];
else
a[i][j] = a[i][j-1] + a[i-j][j];
}
while(t--)
{
cin >> m >> n;
cout << a[m][n] << endl;
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int solve(int i, int j)//求将i个苹果放入j个盘子的方案数
{
if(i == 0 || i == 1 || j == 1)
return 1;
else if(i < j)
return solve(i, i);
else
return solve(i, j-1) + solve(i-j, j);
}
int main()
{
int t, m, n, a[15][15];
cin >> t;
while(t--)
{
cin >> m >> n;
cout << solve(m, n) << endl;
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int a[15][15];//记忆状态:将i个苹果放入j个盘子的方案数
int solve(int i, int j)//求将i个苹果放入j个盘子的方案数
{
if(a[i][j] > 0)
return a[i][j];
if(i == 0 || i == 1 || j == 1)
return 1;
else if(i < j)
return a[i][j] = solve(i, i);
else
return a[i][j] = solve(i, j-1) + solve(i-j, j);
}
int main()
{
int t, m, n, a[15][15];
cin >> t;
while(t--)
{
cin >> m >> n;
cout << solve(m, n) << endl;
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int m, n, ans, numCt;//ans:拆分方式数量 numCt:记录已经拆分了多少数字
void dfs(int a, int st)//对整数a进行一次拆分, 要求拆分出的数字大于等于st
{
for(int i = st; i <= a; ++i)//本次拆分,拆分出数字i
{
numCt++;
if(i == a)//如果数字都拆分完了
ans++;//得到一组方案
else if(numCt < n)//如果已经拆出的数字不足n个,就继续拆
dfs(a - i, i);//这次拆分出数字i,下一次拆分的最小数字为i
numCt--;//状态还原
}
}
int main()
{
int t;
cin >> t;
while(t--)
{
cin >> m >> n;
ans = 0;//状态初始化。numCt在每次运行后一定为0
dfs(m, 1);//对整数m进行一次拆分, 要求拆分出的最小数字是1
cout << ans << endl;
}
return 0;
}