西安电子大学计算机考研复试机试(2019)+ 2011年真题【每位数字加和排序+马鞍点+字符串压缩+Huffman数计算WPL(priority_queue)】

2011 problem A

/*
2011 problem A
cin:n个数字(0,1000) ,0结束 
cout:每位数加和排序输出(小->大)
*/ 
#include<cstdio> 
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
vector<int> v;
int add(int n){
	int sum = 0; 
	while(n/10>0||n%10!=0){ // 数字内部含有0 
		sum += n%10;
		n/=10;
	}
	return sum;
}

int main(){
	int n;
	while(cin>>n){
		if(n != 0){
			v.push_back(add(n));
		}else{
			break;
		}
	}
	sort(v.begin(),v.end());
	for(int i=0;i<v.size();i++){
		cout<<v[i]<<" ";
	}
	cout<<endl;
	return 0;
}

2011 problem B

/*
2011 problem B
给定矩阵的马鞍点。(在所在行最小,所在列最大) 
cin:行数,列数:m,n(1,100)  输入矩阵 
cout:存在:i j a[i][j] 不存在:no
换行
4 4
 9  7  6  8
20 26 22 25
28 36 25 30
12  4  2  6
*/

#include<cstdio> 
#include<iostream>
using namespace std;

int main(){
	int m,n;
	while(cin>>m>>n) {
		int a[m][n];
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				cin>>a[i][j];
			}
		}
		
		int column = 0,row = 0,k; 
		for(int i=0;i<m;i++) {
			// 找到第i行的最小值
			int temp = a[i][0];
//			cout<<"temp:"<<temp<<endl;;
			for(int j=0;j<n;j++){
				if(temp > a[i][j]){
					temp = a[i][j];
					row = i;
					column = j; 
//					cout<<i<<" "<<j<<" "<<temp<<endl;
				}
			}
			// 判断a[row][column]是否是column列的最大值 
			for(k=0;k<n;k++){
				if(a[row][column]<a[k][column]){
//					cout<<a[row][column]<<"not column max!"<<a[k][column]<<"k:"<<k<<endl; 
					break;
				} 
				if(k==n-1){
					cout<<row<<" "<<column<<" "<<a[row][column]<<endl;
				}
			}
				
		}
	}
	return 0;
}

2011 problem C

/*
2011 problem C
字符串压缩,连续的字符个数>=3个进行压缩。
aaaaabbbabaaaaaaaaaaaaaaaabbbb
a5b3aba16b4
本题是要解压缩 
cin:string 长度不超过50
cout: string 长度不超过100
换行 
*/
#include <cstdio> 
#include <cstring>
#include<iostream>
using namespace std;

int main(){
	char a[50];
	int k=0,len=0,type;
	char c;
	cout<<"type:"<<endl;
	cin>>type;
	if(type==0){ // 解压 
		while(cin>>a){
			for(int i=1;i<strlen(a);i++){
				int cnt = 0,count=0;
				while(a[i]>='0'&&a[i]<='9'){ // 个数 
					cnt = cnt*10+a[i++]-'0'; // 字母后的数字提取 
					count++; //  cnt的位数 
				}
				for(int j=0;j<cnt;j++){
					cout<<a[i-count-1];
				}
				if(cnt==0){// 字符后没有数字 
					cout<<a[i-1];
				} 
			}
			cout<<endl;
	 	}		
	}else{  // 压缩 
		while(cin>>a){
			for(int i=0;i<strlen(a);i++){
				int cnt = 1; 
				while(a[i]==a[i+1]){ // 记录连续的重复的元素 
					cnt++;i++;
				}
				if(cnt!=1){
					cout<<a[i]<<cnt;
				}else{
					cout<<a[i];
				}
			}
		} 
		cout<<endl;
	}
	
	return 0;
}

2011 problem D

输入样例: 

8
7 19 2 6 32 21 3 10

输出样例: 

261

哈夫曼树:带权最短路径长度(WPL)最短的二叉树,也叫最优二叉树。

哈夫曼树的构建:将所有结点的权值按从小到大排序,先选择最小的两个结点作为树的初始叶子结点,二者权值之和作为根节点。然后将计算出来的和参与剩余节点权值的排序,继续选择最小的两个,以此类推。

WPL = (2+5)*3+7*2+13*1=48

哈夫曼编码:可以左子树标记0,右子树标记1,每一个结点所形成的01编码不能作为另外一个结点的前缀部分。

如上图:A:111     B:10    C:110    D:0      

这样编码的话形成的01序列就可以辨认出具体是哪个结点,不会出现分辨不清的情况。

算法实现:

我们做题的时候不需要真的构建出哈夫曼树,只需要按照其思想求解出WPL即可 
queue<int> name;
name.front() 队首
name.back() 队尾
name.push(temp) 入队
name.pop() 出队 
name.empty()检测是否为空
name.size() 队列长度 
priority_queue :优先级递减的顺序排序,底层会随时自动调整顺序,最大的元素总在队首
priority_queue<int> q;
priority_queue<int, vector<int>, less<int>> q; 同上面等价,less表示数字大的优先级大,greater表示数字小的优先级越大 
q.top() 队首 
其余方法一致 
一开始我准备用数组来着,都是可行的,当数组的个数大于1时,进行循环,循环体内,先从大到小排序,将最后两个最小的元素加和赋值给temp,a[n-1]=0,a[n-2]=temp;WPL=temp
/*
2011 problem D
通信电文n个字符(4,30)
每个字符出现的频度Wi 
根据权值构建哈夫曼树,计算带权路径长度
cin:n个   频度wi
cout:带权路径长度
*/
#include<iostream>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int> > q; // 注意一档要空格> > ,不能>>
int main() {
	int n;
	int temp,x,y,WPL=0;
	cin>>n;
	// 所有的权值压入队列 
	for(int i=0;i<n;i++){
		cin>>temp;
		q.push(temp);
	}
	// 当队列中个数大于1时进行操作 
	while(q.size()>1){
		x=q.top();
		q.pop();
		y=q.top();
		q.pop();
		q.push(x+y);
		WPL+=x+y;		
	}
	cout<<WPL;
	return 0;
}

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值