持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情
第一题 [USACO3.4] 美国血统 American Heritage
题目描述
农夫约翰非常认真地对待他的奶牛们的血统。然而他不是一个真正优秀的记帐员。他把他的奶牛 们的家谱作成二叉树,并且把二叉树以更线性的“树的中序遍历”和“树的前序遍历”的符号加以记录而 不是用图形的方法。
你的任务是在被给予奶牛家谱的“树中序遍历”和“树前序遍历”的符号后,创建奶牛家谱的“树的 后序遍历”的符号。每一头奶牛的姓名被译为一个唯一的字母。(你可能已经知道你可以在知道树的两 种遍历以后可以经常地重建这棵树。)显然,这里的树不会有多于 26 个的顶点。 这是在样例输入和 样例输出中的树的图形表达方式:
C
/ \
/ \
B G
/ \ /
A D H
/ \
E F
树的中序遍历是按照左子树,根,右子树的顺序访问节点。
树的前序遍历是按照根,左子树,右子树的顺序访问节点。
树的后序遍历是按照左子树,右子树,根的顺序访问节点。
输入格式
第一行: 树的中序遍历
第二行: 同样的树的前序遍历
输出格式
单独的一行表示该树的后序遍历。
样例 #1
样例输入 #1
ABEDFCHG
CBADEFGH
样例输出 #1
AEFDBHGC
提示
题目翻译来自NOCOW。
USACO Training Section 3.4
解题思路
- 1)找到根结点。
- 2)递归左子树。
- 2)递归右子树。
参考代码
#include <bits/stdc++.h>
using namespace std;
string s1,s2;
void houxu(int l1,int r1,int l2,int r2)
{
int m=s2.find(s1[l1]);
if(m>l2) houxu(l1+1,l1+m-l2,l2,m-1);
if(m<r2) houxu(l1+m-l2+1,r1,m+1,r2);
cout<<s1[l1];
}
int main()
{
cin>>s2>>s1;
houxu(0,s1.size()-1,0,s2.size()-1);
return 0;
}
第二题 生日
题目描述
cjf 君想调查学校 OI 组每个同学的生日,并按照年龄从大到小的顺序排序。但 cjf 君最近作业很多,没有时间,所以请你帮她排序。
输入格式
输入共有 行,
第 行为 OI 组总人数 ;
第 行至第 行分别是每人的姓名 、出生年 、月 、日 。
输出格式
输出共有 行,
即 个生日从大到小同学的姓名。(如果有两个同学生日相同,输入靠后的同学先输出)
样例 #1
样例输入 #1
3
Yangchu 1992 4 23
Qiujingya 1993 10 13
Luowen 1991 8 1
样例输出 #1
Luowen
Yangchu
Qiujingya
提示
数据保证,,。保证年月日实际存在,且年份 。
解题思路
- 1)结构体的比较排序。
参考代码
#include<bits/stdc++.h>
using namespace std;
int i,j,k,n,m;
struct student{
string name;
int year,mon,day,level;
}a[1001];
int cmp(student a,student b)
{
if(a.year != b.year)
return a.year < b.year;
else
{
if(a.mon != b.mon) return a.mon < b.mon;
else if(a.day == b.day && a.mon == b.mon) return a.level > b.level;
else if(a.day != b.day && a.mon == b.mon) return a.day < b.day;
}
}
int main()
{
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i].name>>a[i].year>>a[i].mon>>a[i].day;
a[i].level=i;
}
sort(a+1,a+1+n,cmp);
for(i=1;i<=n;i++)
cout<<a[i].name<<endl;
return 0;
}
第三题 [NOIP2001 提高组] 数的划分
题目描述
将整数 分成 份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:,,下面三种分法被认为是相同的。
;
;
.
问有多少种不同的分法。
输入格式
(,)
输出格式
个整数,即不同的分法。
样例 #1
样例输入 #1
7 3
样例输出 #1
4
提示
四种分法为:
;
;
;
.
解题思路
- 1)深度优先搜索。
参考代码
#include<bits/stdc++.h>
using namespace std;
int ans;
void dfs(int x,int n,int k)
{
if(n==1)
{
ans++;
return;
}
for(int i=x;i<=k/n;i++)
dfs(i,n-1,k-i);
}
int main()
{
int n,k;
cin>>n>>k;
dfs(1,k,n);
cout<<ans;
return 0;
}
第四题 [BOI2009]Radio Transmission 无线传输
题目描述
给你一个字符串 ,它是由某个字符串 不断自我连接形成的。但是字符串 是不确定的,现在只想知道它的最短长度是多少。
输入格式
第一行一个整数 ,表示给出字符串的长度。
第二行给出字符串 的一个子串,全由小写字母组成。
输出格式
仅一行,表示 的最短长度。
样例 #1
样例输入 #1
8
cabcabca
样例输出 #1
3
提示
样例输入输出 1 解释
对于样例,我们可以利用 不断自我连接得到 ,读入的 ,是它的子串。
规模与约定
对于全部的测试点,保证 。
解题思路
- 1)kmp算法。
参考代码
#include<cstdio>
using namespace std;
int n,next[1000050];
char ss[1000050];
int main()
{
scanf("%d%s",&n,ss+1);
int j=0;
for(int i=2;i<=n;++i)
{
while(j&&ss[i]!=ss[j+1]) j=next[j];
if(ss[i]==ss[j+1]) ++j;
next[i]=j;
}
printf("%d",n-kmp[n]);
return 0;
}