【递归/DP】整数划分
原创
©著作权归作者所有:来自51CTO博客作者鱼竿钓鱼干的原创作品,请联系作者获取转载授权,否则将追究法律责任
整数划分问题
放苹果
题目
思路
这题是允许空盘子的
DP没写出来,递归也没想明白,属实蒟蒻了
递归的想法
m<1的时候都有一种
n==1的时候有一种
然后考虑一般数据
如果苹果数>=盘子数,我们有两种选择
所有盘子放一个苹果f(m-n,n),或者选一个盘子不放东西f(m,n-1)
如果苹果数<盘子数,我们肯定有盘子是不放的f(m,n-1),直接点是f(m,m)
代码
// Problem: P2386 放苹果
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2386
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// FishingRod
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;
typedef pair<int,int> PII;
/*DATA & KEY
n 1 10
m 1 10
t 0 20
*/
int T;
int work(int m,int n)
{
if(m<1||n==1)return 1;
if(m>=n)return work(m,n-1)+work(m-n,n);
else return work(m,m);
}
void solve(int T)
{
//NEW DATA CLEAN
//NOTE!!!
int n,m;cin>>m>>n;
cout<<work(m,n)<<endl;
}
int main()
{
scanf("%d",&T);
while(T--)solve(T);
return 0;
}
数的划分
思路
和上题的区别是这题不能为空,那么先每个盘子放一个然后就能转化为和上题一样的题目了
代码
// Problem: P1025 [NOIP2001 提高组] 数的划分
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1025
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// FishingRod
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long LL;
typedef pair<int,int> PII;
/*DATA & KEY
*/
int T;
LL f[205][10];
LL work(int n,int k)
{
if(f[n][k]!=-1)return f[n][k];
if(n<=1||k==1)return f[n][k]=1;
if(n>=k)return f[n][k]=work(n-k,k)+work(n,k-1);
else return f[n][k]=work(n,n);
}
void solve()
{
//NEW DATA CLEAN
memset(f,-1,sizeof f);
//NOTE!!!
int n,k;cin>>n>>k;
cout<<work(n-k,k)<<endl;
}
int main()
{
// scanf("%d",&T);
// while(T--)solve(T);
solve();
return 0;
}
279. 自然数拆分
思路
完全背包问题
由于至少选2个所以总共n-1个物品,体积为1~n-1。然后求方案数
二维
目标为
可以省略第一维度
目标为
代码
//Title:279. 自然数拆分
//URL:https://www.acwing.com/problem/content/281/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=4005,mod=2147483648;
int n;
LL f[N];
//物品1~n-1
int main()
{
cin>>n;
f[0]=1;
for(int i=1;i<=n-1;i++)
{
for(int j=i;j<=n;j++)
{
f[j]+=f[j-i]%mod;
f[j]%=mod;
}
}
cout<<f[n];
return 0;
}
总结
整数划分问题需要注意是否允许空盘,有没有限定分组数量。
一半这类问题有以下思考方向:递归(确定组数的),背包DP(不限组数的),DFS回溯(数据量小的),数学方法(排列组合,生成函数)