Entropy(poj 1521)
题目大意
对字符串分别用ASCII编码(每个字符8b)和哈夫曼编码,输出编码前、后的长度并计算压缩比。
解题思路
本题不要求求出编码,只需计算长度,考虑记录字符出现频次,用优先队列记录最小的两个频次,直接计算长度。
未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
priority_queue<int,vector<int>,greater<int>>q;
string s;
while(getline(cin,s)&&s!="END"){
sort(s.begin(),s.end());
int cnt=1;
int len=s.size();
for(int i=1;i<=len;i++){
if(s[i]!=s[i-1]){
q.push(cnt);
cnt=1;
}else cnt++;
}
int ans=0;
if(q.size()==1)ans=len;
while(q.size()>1){
int a=q.top();
q.pop();
int b=q.top();
q.pop();
q.push(a+b);
ans+=(a+b);
}
q.pop();
cout<<len*8<<" "<<ans<<" "<<len*8.0/ans<<endl;
}
return 0;
}
Safe Or Unsafe(hdu P2527)
题目大意
对字符串按哈夫曼编码统计总权值即频次,判断是否小于等于给定值。这道题与上一题基本相同。
解题思路
对字符串排序,统计字符串频次,将其作为节点权值,利用优先队列计算总和。
未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
priority_queue<int,vector<int>,greater<int>>q;
int n,t;
string s;
cin>>n;
while(n--){
cin>>t>>s;
sort(s.begin(),s.end());
int cnt=1;
int len=s.size();
for(int i=1;i<=len;i++){
if(s[i]!=s[i-1]){
q.push(cnt);
cnt=1;
}else cnt++;
}
int ans=0;
if(q.size()==1)ans=len; //只有一种字符,长度即为频次
while(q.size()>1){
int a=q.top();
q.pop();
int b=q.top();
q.pop();
q.push(a+b);
ans+=(a+b);
}
q.pop();
if(ans<=t)puts("yes");
else puts("no");
}
return 0;
}
FBI树(洛谷P1087)
题目大意
根据给出的01串建树,输出相应后续遍历字符序列。
解题思路
依据题目意思,采用先序遍历的方式建树,即根左右,对01串的操作类似于二分。递归函数先对左右建树并输出节点字符,最后输出根节点字符,对应后序遍历。
未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
string s;
cin>>s;
function<void(int,int)>build=[&](int l,int r){
if(l<r){
int mid=(l+r)>>1;
build(l,mid);
build(mid+1,r);
}
int a=0,b=0;
for(int i=l;i<=r;i++){
if(s[i]=='0')a++;
else b++;
}
if(a&b)cout<<"F";
else if(a)cout<<"B";
else cout<<"I";
};
build(0,(1<<n)-1);
return 0;
}
求先序排列(洛谷P1030)
题目大意
根据二叉树的中序与后续排列求前序排列。
解题思路
中序遍历左根右,后序遍历左右根,依据上述特点,先取后序排列最后一个字符即为根且易知为树的整个树的根,然后在中序排列里查找这个根,并将其分为左右两个子树序列,那么对应的后序排列也可分为两个子树序列,重复上述操作输出所有节点即为先序遍历,按照根左右输出。
未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
string instr,poststr;
cin>>instr>>poststr;
function<void(string,string)>build=[&](string instr,string poststr){
if(instr.size()<=0)return;
cout<<poststr.back();
int mid=instr.find(poststr.back());
build(instr.substr(0,mid),poststr.substr(0,mid));
build(instr.substr(mid+1),poststr.substr(mid,instr.size()-mid-1)); //注意后序排列
};
build(instr,poststr);
return 0;
}
新二叉树(洛谷P1305)
题目大意
输入二叉树每个节点的根左右字符串,求先序序列。
解题思路
解法1:根据条件建树,并递归输出先序序列。
解法2:根据先序序列性质,根据给出的根左右单节点字符序进行拼接,'*'可以不做处理,输出时判断跳过即可。
建树解法
#include<bits/stdc++.h>
using namespace std;
struct BTree{
char ch;
BTree*l,*r;
BTree(){}
BTree(char ch):ch(ch),l(nullptr),r(nullptr){}
}tree;
BTree*build(char ch){
if(ch=='*')return nullptr;
return new BTree(ch);
}
BTree*find_node(char ch,BTree*t){
if(t->ch==ch)return t;
BTree*ans=nullptr;
if(t->l)ans=find_node(ch,t->l);
if(ans!=nullptr)return ans;
if(t->r)ans=find_node(ch,t->r);
return ans;
}
void prevorder(BTree*t){
cout<<t->ch;
if(t->l)prevorder(t->l);
if(t->r)prevorder(t->r);
}
int main(){
int n;
cin>>n;
char root,l,r;
cin>>root>>l>>r;
tree.ch=root;
tree.l=build(l);
tree.r=build(r);
for(int i=1;i<n;i++){
cin>>root>>l>>r;
BTree*node=find_node(root,&tree);
node->l=build(l);
node->r=build(r);
}
prevorder(&tree);
return 0;
}
搜索解法
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
string s;
cin>>n>>s;
for(int i=1;i<n;i++){
string ret;
cin>>ret;
int pos=s.find(ret[0]);
s.erase(pos,1);
s.insert(pos,ret); //直接拼接
}
for(auto&it:s){
if(it!='*')cout<<it;
}
return 0;
}
遍历问题(洛谷P1229)
题目大意
给定二叉树前序遍历和后序遍历结果,求中序遍历种数。
解题思路
依据题意可知,当节点只存在一个儿子时,它既可以做左子树又可以做右子树,会在已知前、后序的条件下存在不同的中序遍历结果,那么求有多少个节点只有一个儿子,然后依据乘法原理不断乘2即可。如果该节点有一个子节点,那么它在前序遍历序列中的下一个节点一定是它的子节点,同时在后序遍历序列中的位置一定是在它的前一个节点的位置。
未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int ans=1;
string s1,s2;
cin>>s1>>s2;
int len=s1.size();
for(int i=0;i<len-1;i++){
for(int j=1;j<len;j++){
if(s1[i]==s2[j]&&s1[i+1]==s2[j-1])ans<<=1;
}
}
cout<<ans<<endl;
return 0;
}
对称二叉树(洛谷P5018)
题目大意
根据给定信息的二叉树,找出最大对称(在结构和权值上均对称)二叉树的节点数。
解题思路
创建递归函数,递归遍历左右子树,判断是否相等。记录节点数最值。
未知的代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
struct node{
int l,r,v;
}a[N];
bool dfs(int x,int y){
if(x==-1&&y==-1)return true;
if(x==-1||y==-1)return false;
if(a[x].v!=a[y].v)return false;
return dfs(a[x].l,a[y].r)&&dfs(a[x].r,a[y].l);
}
int count(int x){ //递归求节点数
return x==-1?0:count(a[x].l)+count(a[x].r)+1;
}
signed main(){
int n,ans=0;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i].v;
for(int i=1;i<=n;i++)cin>>a[i].l>>a[i].r;
for(int i=1;i<=n;i++){
if(dfs(i,i))ans=max(ans,count(i));
}
cout<<ans;
return 0;
}
复读(洛谷P5597)
题目大意
解题思路
荷马史诗(洛谷P2168)
题目大意
解题思路
标签:遍历,return,哈夫曼,int,cin,ch,二叉树,节点 From: https://www.cnblogs.com/eternal-world/p/17931532.html