我们先慢慢来
- 加分二叉树
- 题目
- 题解
- 简单讲解前序//中序//后序遍历
- 代码实现
- 太空梯
- 题目
- 题解
- 代码实现
加分二叉树
题目
题解
简单讲解前序//中序//后序遍历
其实说白了,这个*序就是根root的遍历顺序
先序就是root–>left–>right
中序就是left–>root–>right
后序就是left–>right–>root
上图:
那么这个图很完美啊!!有两个儿子的,又有只有左儿子的,还有只有右儿子的
先序:1 2 4 3 5
中序:4 2 1 3 5
后序:4 2 5 3 1
以讲解先序遍历顺序为例:
首先找到根root=1,然后再去搜索左儿子2,这个时候2为新子树的根,
接着搜索2的左儿子4,4是叶子节点回溯,其次搜索2的右儿子,无,回溯
回到最上面搜索1的右儿子3,然后搜索3的左儿子,空,回溯,
最后找到右儿子5,叶子节点,回溯
讲解一个顺序把近几年所学的逻辑顺序词给憋完了
那么这道题其实就很水,加上数据那么小,直接暴力跑生成树就ok了
对于搜索的这个新子树的范围l,r,枚举这之间任何一个i为根的情况,
求个MAX
记录个root=i,最后用递归输出即可
代码实现
#include <cstdio>
#define MAXN 35
int dp[MAXN][MAXN];
int root[MAXN][MAXN];
int a[MAXN];
int n;
void build ( int l, int r ) {if ( dp[l][r] ) return;if ( l > r ) {dp[l][r] = 1;return;}if ( l == r ) {dp[l][r] = a[l];root[l][r] = l;return;}for ( int i = l;i <= r;i ++ ) {build ( l, i - 1 );build ( i + 1, r );if ( dp[l][i - 1] * dp[i + 1][r] + a[i] > dp[l][r] ) {dp[l][r] = dp[l][i - 1] * dp[i + 1][r] + a[i];root[l][r] = i;}}
}
void print ( int l, int r ) {if ( ! root[l][r] ) return;printf ( "%d ", root[l][r] );print ( l, root[l][r] - 1 );print ( root[l][r] + 1, r );
}
int main() {scanf ( "%d", &n );for ( int i = 1;i <= n;i ++ ) scanf ( "%d", &a[i] );build ( 1, n );printf ( "%d\n", dp[1][n] );print ( 1, n );return 0;
}
太空梯
题目
题目描述
有一群牛要上太空。他们计划建一个太空梯-----用一些石头垒。他们有k(1<=k<=400)种不同类型的石头,每一种石头的高度为h_i(1<=h_i<=100),数量为c_i(1<=c_i<=10),并且由于会受到太空辐射,每一种石头不能超过这种石头的最大建造高度a_i(1<=a_i<=40000)。帮助这群牛建造一个最高的太空梯。
输入格式
第一行为一个整数即k。第2行到第k+1行每一行有3个数,代表每种类型魔法石的特征,即高度h,限制高度a和数量c。
输出格式
一个整数,即修建太空梯的最大高度。
样例
样例输入
3
7 40 3
5 23 8
2 52 6
样例输出
48
【样例说明】 15+21+12
最底下为3块石头2型,中间为3块石头1型,上面为6块石头3型。放置4块石头2型和3块石头1型是不可以的,因为顶端的石头1型的高度超过了40的限制。
题解
这道题也是一个多重背包水题
首先肯定会想到排序,因为石头类型的高度限制越小,肯定越往下排,往上很容易超过最高限制
然后我们就定义一个:bool类型的dp[i][j]
表示只使用1~i种类型石头且总高度为j的剋行性,
可以凑出来并且合法就是1,反之0
dp[i][j]=max(dp[i-1][j],dp[i-1][j-k*stone[i].h]) k表示i石头使用的个数
我们知道dp[i][j]只与i-1上一种石头类型有关
所以我们就简化成一维
dp[j]=max(dp[j], dp[j-k*stone[i].h])
这里还是像其他dp题一样,j要从大到小枚举
简单解释为什么;
当我们i++后要重新开始枚举j,如果是从小到大,
因为我们是一维,就会对上一次i改变后的答案进行更改
而我们到后面的会有 j - k * stone[i].h 的操作,这个时候我们其实是需要i-1的状态,
如果从小到大状态答案就被覆盖了,最后ans也会出错
代码实现
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 405
#define MAX 40005
struct node {int h, limit, c;
}stone[MAXN];
bool cmp ( node x, node y ) {return x.limit < y.limit;
}
int n, Max;
bool dp[MAX];
int main() {scanf ( "%d", &n );for ( int i = 1;i <= n;i ++ ) {scanf ( "%d %d %d", &stone[i].h, &stone[i].limit, &stone[i].c );Max = max ( Max, stone[i].limit );}sort ( stone + 1, stone + n + 1, cmp );dp[0] = 1;for ( int i = 1;i <= n;i ++ )for ( int j = Max;j >= 0;j -- )for ( int k = 0;k <= stone[i].c;k ++ ) {if ( j < k * stone[i].h || j > stone[i].limit ) break;else dp[j] = max ( dp[j], dp[j - k * stone[i].h] );}for ( int i = Max;i >= 0;i -- )if ( dp[i] ) {printf ( "%d\n", i );break;}return 0;
}
好了,就到这里吧,这只是练练手,不然怎么叫专练1呢~~
等会儿我就会携带着一堆毒瘤来见大家的,bye~