ALGO-20. 求先序排列列!!!!
问题描述
给出⼀一棵二叉树的中序与后序排列。求出它的先序排列列。(约定树结点⽤不同的⼤写字母表示,⻓度
<=8)。
输⼊入格式
两行,每行⼀个字符串,分别表示中序和后序排列
输出格式
⼀个字符串,表示所求先序排列
样例例输⼊入
BADC
BDCA
样例例输出
ABCD
#include<iostream>
#include<string.h>
using namespace std;
string in,post,ans="";
void pre(int root,int l,int r){
if(l>r) return;
int i=r;
while(post[root]==in[i])
i--;
ans+=post[i];
pre(root-1+i-1,l,i-1);
pre(root-1,i+1,r);
}
int main(){
cin>>in>>post;
pre(post.length()-1,0,in.length()-1);
cout<<ans;
return 0;
}
这里采用递归的方法进行
同类型扩展:
知先序遍历、中序遍历求后序遍历:
#include <cstdio>
#include <cstring>
const int maxn = 100;
int n;
char a[maxn], b[maxn];
void dfs(int la, int ra, int lb, int rb) {
printf("%d %d %d %d",&la,&ra,&lb,&rb);
if (la > ra)
return;
int md;
for (md = la; a[md] != b[lb]; md ++);
dfs(la, md - 1, lb + 1, lb + md - la);
dfs(md + 1, ra, lb + md - la + 1, rb);
putchar(b[lb]);
}
int main() {
scanf("%s", b + 1);
scanf("%s", a + 1);
n = strlen(a + 1);
dfs(1, n, 1, n);
putchar(10);
}
ALGO-21. 装箱问题(动态规划,01背包)
问题描述
有⼀一个箱⼦子容量量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品
有⼀一个体积(正整数)。
要求n个物品中,任取若⼲干个装⼊入箱内,使箱⼦子的剩余空间为最⼩小。
输⼊入格式
第⼀一⾏行行为⼀一个整数,表示箱⼦子容量量;
第⼆二⾏行行为⼀一个整数,表示有n个物品;
接下来n⾏行行,每⾏行行⼀一个整数表示这n个物品的各⾃自体积。
输出格式
⼀一个整数,表示箱⼦子剩余空间。
样例例输⼊入
24
6
8
3
12
7
9
7
样例例输出
0
思考:
一般这种寻求合不合适的方案用动态规划进行
dp[i][j]代表前i中东西放置到体积为j的包内
如果物品体积能够放进去:
可以选择放或者不放
dp[i][j]=max(dp[i-1][j],dp[i-1][j-t]+t)
如果物品体积不能够放进去:
dp[i][j]=dp[i-1][j]
最后输出v-dp[n][v]即可
#include<iostream>
#include<vector>
using namespace std;
int dp[31][20001];
int main(){
int v,n;
cin>>v>>n;
int t;
for(int i=1;i<=n;i++)
{
cin>>t;
for(int j=1;j<=v;j++)
{
if(j>=t)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-t]+t);
else
dp[i][j]=dp[i-1][j];
}
}
cout<<v-dp[n][v];
return 0;
}
ALGO-29. 校⻔门外的树(区间处理理)
问题描述
某校⼤大⻔门外⻓长度为L的⻢马路路上有⼀一排树,每两棵相邻的树之间的间隔都是1⽶米。我们可以把⻢马路路看
成⼀一个数轴,⻢马路路的⼀一端在数轴0的位置,另⼀一端在L的位置;数 轴上的每个整数点,即0,1,2,
……,L,都种有⼀一棵树。
由于⻢马路路上有⼀一些区域要⽤用来建地铁。这些区域⽤用它们在数轴上的起始点和终⽌止点表示。已 知任
⼀一区域的起始点和终⽌止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树
(包括区域端点处的两棵树)移⾛走。你的任务是计算将这些树 都移⾛走后,⻢马路路上还有多少棵树。
输⼊入格式
输⼊入⽂文件的第⼀一⾏行行有两个整数L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表⻢马路路的⻓长
度,M代表区域的数⽬目,L和M之间⽤用⼀一个空格隔开。接下来的M⾏行行每⾏行行包含两个不不同的整数,⽤用⼀一个
空格隔开,表示⼀一个区域的起始点 和终⽌止点的坐标。
输出格式
输出⽂文件包括⼀一⾏行行,这⼀一⾏行行只包含⼀一个整数,表示⻢马路路上剩余的树的数⽬目。
样例例输⼊入
500 3
150 300
100 200
470 471
样例例输出
298
数据规模和约定
对于20%的数据,区域之间没有重合的部分;
对于其它的数据,区域之间有重合的情况。
思考:
通过动态数组进行筛选就很简单了
注意它是由0开始的
#include<iostream>
#include<vector>
using namespace std;
int main(){
int L,M;
cin>>L>>M;
vector<int >v(L+1,1);
int a,b;
int count=0;
while(M--)
{
cin>>a>>b;
for(int i=a;i<=b;i++)
v[i]=0;
}
for(int i=0;i<=L;i++)
if(v[i]==1)
count++;
cout<<count;
return 0;
}
ALGO-30. ⼊入学考试(01背包,动态规划)
问题描述
⾠辰辰⾠辰辰是个天资聪颖的孩⼦子,他的梦想是成为世界上最伟⼤大的医师。为此,他想拜附近最有威望的
医师为师。医师为了了判断他的资质,给他出了了⼀一个难题。医师把他带到⼀一个到处都是草药的⼭山洞洞⾥里里对
他说:“孩⼦子,这个⼭山洞洞⾥里里有⼀一些不不同的草药,采每⼀一株都需要⼀一些时间,每⼀一株也有它⾃自身的价值。
我会给你⼀一段时间,在这段时间⾥里里,你可以采到⼀一些草药。如果你是⼀一个聪明的孩⼦子,你应该可以让
采到的草药的总价值最⼤大。”
如果你是⾠辰辰⾠辰辰,你能完成这个任务吗?
输⼊入格式
第⼀一⾏行行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),⽤用⼀一个空格隔开,T代表总共能
够⽤用来采药的时间,M代表⼭山洞洞⾥里里的草药的数⽬目。接下来的M⾏行行每⾏行行包括两个在1到100之间(包括1
和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出格式
包括⼀一⾏行行,这⼀一⾏行行只包含⼀一个整数,表示在规定的时间内,可以采到的草药的最⼤大总价值。
样例例输⼊入
70 3
71 100
69 1
1 2
样例例输出
3
数据规模和约定
对于30%的数据,M <= 10;
对于全部的数据,M <= 100。
思考:
看题目获得最大总价值就可以知道它是要通过动态规划进行
dp[i][j]代表前i秒采草时包内容量为j,整个值的大小表示的是采草药的最大价值
如果包内容量能够放进去:
可以选择放或者不放
dp[i][j]=max(dp[i-1][j],dp[i-1][j-t]+v)
如果包内容量不能够放进去:
dp[i][j]=dp[i-1][j]
最后输出dp[m][T]即可
#include<iostream>
#include<cstring>
using namespace std;
int dp[100][1000];
int main(){
memset(dp,0,sizeof(dp));
int T,m;
cin>>T>>m;
int t,v;
for(int i=1;i<=m;i++)
{
cin>>t>>v;
for(int j=1;j<=T;j++)
{
if(j>=t)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-t]+v);
else
dp[i][j]=dp[i-1][j];
}
}
cout<<dp[m][T];
return 0;
}
ALGO-31. 开⼼心的⾦金金明(01背包,动态规划)
问题描述
⾦金金明今天很开⼼心,家⾥里里购置的新房就要领钥匙了了,新房⾥里里有⼀一间他⾃自⼰己专⽤用的很宽敞的房间。更更
让他⾼高兴的是,妈妈昨天对他说:
“你的房间需要购买哪些物品,怎 么布置,你说了了算,只要不不超过N元钱就⾏行行”。今天⼀一早⾦金金明就开始
做预算,但是他想买的东⻄西太多了了,
肯定会超过妈妈限定的N元。于是,他把每件物品规定了了⼀一 个重要度,分为5等:⽤用整数1~5表示,第
5等最重要。他还从因特⽹网上查到了了每件物品的价格(都是整数元)。他希望在不不超过N元(可以等于
N元)的前提 下,使每件物品的价格与重要度的乘积的总和最⼤大。
设第j件物品的价格为v[j],重要度为w[j],共选中了了k件物品,编号依次为 j1,j2,……,jk,则所
求的总和为:
v[j1]*w[j1]+v[j2]w[j2]+ …+v[jk]w[jk]。(其中为乘号)
请 你帮助⾦金金明设计⼀一个满⾜足要求的购物单。
输⼊入格式
输⼊入⽂文件 的第1⾏行行,为两个正整数,⽤用⼀一个空格隔开:
N m
(其中N(<30000)表示总钱 数,m(<25)为希望购买物品的个数。)
从第2⾏行行到第m+1⾏行行,第j⾏行行给出了了编号为j-1的物品的基本数据,每⾏行行有2个⾮非负整数
v p
(其中v表示该物品的价格(v<=10000),p表示该物品的重要度(1~5))
输出格式
输出⽂文件只有⼀一个正整数,为不不超过总钱数的物品的价格与重要度乘积的总和的最⼤大值
(<100000000)。
样例例输⼊入
1000 5
800 2
400 5
300 5
400 3
200 2
样例例输出
3900
思考:
老样子!获得最大值即是动态规划问题,分为买或者不买
dp[i][j]表示对于前i件物品选择部分购买限定总价不不超过j元后,物品的价格与重要程度乘积的总和的最
大值
可得dp[m][n]即是所求的解。
1.当当前输⼊入的物品价格⼤大于允许的最⼤大总价j元,则不不买,dp[i][j] = dp[i-1][j];
2.当当前输⼊入的物品体积⼩小于等于允许的最⼤大总价j元,考虑买或者不不买两种状态,取物品的价格与重
要程度乘积的总和最⼤大的那个:dp[i][j]=max(dp[i-1][j],dp[i-1][j-v]+vp);
#include<iostream>
#include<cstring>
using namespace std;
int dp[25][30000];
int main(){
memset(dp,0,sizeof(dp));
int N,m;
cin>>N>>m;
int v,p;
for(int i=1;i<=m;i++)
{
cin>>v>>p;
for(int j=1;j<=N;j++)
{
if(j>=v)
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v]+v*p);
else
dp[i][j]=dp[i-1][j];
}
}
cout<<dp[m][N];
return 0;
}
ALGO-34. 纪念品分组(贪⼼心算法+排序)
问题描述
元旦快到了了,校学⽣生会让乐乐负责新年年晚会的纪念品发放⼯工作。为使得参加晚会的同学所获得的
纪念品价值 相对均衡,他要把购来的纪念品根据价格进⾏行行分组,但每组最多只能包括两件纪念品,并
且每组纪念品的价格之和不不能超过⼀一个给定的整数。为了了保证在尽量量短的时 间内发完所有纪念品,乐
乐希望分组的数⽬目最少。
你的任务是写⼀一个程序,找出所有分组⽅方案中分组数最少的⼀一种,输出最少的分组数⽬目。
输⼊入格式
输⼊入包含n+2⾏行行:
第1⾏行行包括⼀一个整数w,为每组纪念品价格之和的上限。
第2⾏行行为⼀一个整数n,表示购来的纪念品的总件数。
第3~n+2⾏行行每⾏行行包含⼀一个正整数pi (5 <= pi <= w),表示所对应纪念品的价格。
输出格式
输出仅⼀一⾏行行,包含⼀一个整数,即最少的分组数⽬目。
样例例输⼊入
100
9
90
20
20
30
50
60
70
80
90
样例例输出
6
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int w,n;
cin>>w>>n;
int s[n];
int count=0;
for(int i=0;i<n;i++)
{
cin>>s[i];
}
sort(s,s+n);
for(int i=0;i<n;i++)
{
if(s[i]>4)
for(int j=0;j<=n;j++)
if(s[n-j]>4&&(s[i]+s[n-j]<=w))
{
count++;
s[i]=s[n-j]=1;
break;
}
}
for(int i=0;i<n;i++)
if(s[i]>=5)
count++;
cout<<count;
return 0;
}
我的方法太麻烦,要经历多次遍历
这种方法就简单多了:
首先排好顺序,i和j两两组合,若能组合的就成为一组,若i和j不能组合在一起,i-1和j更不能组合在一起,所以j只能自己成为一组了(这样可以避免后序在经历一次遍历),这时只需要看i能不能和j-1有一次遍历
循环的条件是i<=j,假设i和j相邻,便尝试一下两两能不能组合;如果不不满⾜足把它们放⼊⼀一组,那么j放⼊⼀组后j移动指针,使i == j,继续进⼊入循环;
当i == j的时候,因为这个单独的物品已经没有可以组合的物品剩余了,所以此时还要进⼊循环进行一
次 count++ 的计数操作~
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int main() {
int w, n;
scanf("%d %d", &w, &n);
int *a = new int[n];
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
sort(a, a+n);
int i = 0, j = n-1, cnt = 0;
while(i <= j) {
if(a[i] + a[j] <= w) {
i++;
}
cnt++;
j--;
}
cout << cnt;
return 0;
}