电子学会四级-动态规划
技能树
sum i j 高度小于等于i 节点数为j的二叉树个数
sum i-1 j 高度小于等于i-1 节点数为j的二叉树个数
dp i j 高度等于i 节点数为j的二叉树个数
sum i j = sum i-1 j + dp i j
右子树不同二叉树个数
sum i-1 j-1-k
左子树和右子树分别完成种类数的一部分,所以使用乘法原理得到总的种类数
此时,这课原来高度为i,节点数为j的树包含二叉树个数为 dp i-1 k * sum i-1 j-1-k
同理,右子树也可以是高度为i-1的子树,那么总的二叉树个数也前面左子树高度为i-1相同,总二叉树个数为
(dp i-1 k * sum i-1 j-1-k) * 2
注意 有一种情况在左右子树分别计算时,被算了两次,即:左右子树高都为i-1时,这种情况二叉树个数为
dp i-1 k * dp i-1 j-k-1 j总节点数-k左子树接点数-1 根节点
#include<bits/stdc++.h>
using namespace std;
#define N 310
#define M 110
#define mod 9901
int f[M][N],sum[N][M];
int main(){
int n,m;
scanf("%d%d",&n,&m);
f[1][1]=sum[1][1]=1;
for (int j=2; j<=n; j++)
f[1][j]=sum[1][j]=0;
for (int i=2; i<=m; i++){
for (int j=1; j<=n; j++){
f[i][j]=0;
for (int k=1; k<j; k++)
f[i][j]=(f[i][j]+(2*f[i-1][k]*sum[i-1][j-k-1]-f[i-1][k]*f[i-1][j-k-1])%mod)%mod;
sum[i][j]=(sum[i-1][j]+f[i][j])%mod;
}
}
printf("%d\n",f[m][n]);
return 0;
}
2000 最长公共子上升序列
题解
dp[j]表示a取到1 .. i,b取到1 .. j,且以b[j]结尾的最长公共上升子序列
a[i]==b[j]时,需要取前面比b[j]小的最长公共上升子序列+1
比如:
2 6
2 6
dp[1]=1两个2是第一个最长公共上升子序列
黑色的6相等,所以为dp[1]+1=2
a[i]>b[j]时,存储maxdp=max(dp[j]) 即为a取1 .. i-1,b取1 .. j的最长公共上升子序列
例如
2 6
2 6
a取到1 .. 2,b取1时,dp[1]=1 maxdp=1,为a取到1 .. 2,b取1 .. 2时,数据赋值做准备
a[i]<b[j]不对最长公共上升子序列做贡献
例如
7 6
7 6
黑色字体6<7 虽然dp[1]=1,并且6 6是相同 并不是上升的,因此不应该在dp[1]基础上累加本次相同的6
#include<bits/stdc++.h>
using namespace std;
int a[505],b[505];
struct node{
vector<int> v;
int val=0;//初始化
}dp[505];//a取1~i b取1~j且以b[j]结尾的最长公共上升子序列
int main(){
int n,m;
cin>>m;
for(int i=1;i<=m;i++){
cin>>a[i];
}
cin>>n;
for(int i=1;i<=n;i++){
cin>>b[i];
}
for(int i=1;i<=m;i++){
//a取1~i b取1~j且以b[j]结尾的最长公共上升子序列
node maxn;
for(int j=1;j<=n;j++){
//1.a[i]>b[j]时maxn 找比a[i]小且以b[j]结尾的最长公共上升子序列
//2.其中1中最长公共上升子序列为a取1~i-1 b取1~j-1 时组成的
//3.为a[i]==b[j]时为dp[j]赋值做准备
if(a[i]>b[j]&&maxn.val<dp[j].val){
maxn=dp[j];
}
//必须相等才可能组成公共子序列
if(a[i]==b[j]){
//相等时长度在之前最长基础加1
dp[j].val=maxn.val+1;
//复制之前最长序列
dp[j].v=maxn.v;
dp[j].v.push_back(b[j]);
}
}
}
//循环取出dp[].val最长的
node maxn=dp[1];
for(int i=2;i<=n;i++){
if(dp[i].val>maxn.val){
maxn=dp[i];
}
}
//输出最长值
cout << maxn.val <<endl;
//输出最长序列
for(int i=0;i<maxn.v.size();i++){
cout << maxn.v[i] << " ";
}
return 0;
}
作者:newcode 更多资源请关注纽扣编程微信公众号
从事机器人比赛、机器人等级考试、少儿scratch编程、信息学奥赛等研究学习