FAFU 專業技能考核題目模擬題解析(僅供參考)


排序


思路:
直接做一次排序 然后特判一下即可
需要注意輸出格式是在每個數前輸出空格
排序推薦直接使用c++的sort函數
需要下面這兩句引入

#include <algorithm>
using namespace std;

代碼:

#include "stdio.h"
#include <algorithm>
using namespace std;

int main(){
	int a[1005],b[1005], n, i, j, k, m, t, aver=0;
	
	FILE *fp;
	if((fp=fopen("sort.in", "r")) != NULL ){
		fclose(fp);  //存在的話,要先把之前打開的文件關掉
		
		freopen("sort.in", "r", stdin);
		//freopen("sort.out", "w", stdout);
	}
	
	scanf("%d", &n);
	for( i=0; i<n; i++){
		scanf("%d", &a[i]);
		aver += a[i];
	}
	aver = (int)(1.0*aver/n + 0.5) ;
	//********************************************************

	//為a數組從小到大排序
	sort(a,a + n);
	
	k = 0;//記錄到哪個位置 大於平均數
	
	for(i = 0; i < n; i++){
		if(a[i] <= aver){
			printf(" %d",a[i]);
		}
		else {  //此時大於平均數 要逆序輸出 
			k = i;
			break;
		}
	} 

	//開始逆序輸出
	for(i = n-1;i >= k;i--){
		printf(" %d",a[i]);
	} 
	
	//========================================================
	return 0;
}

哈夫曼樹(比較難)


思路:
最麻煩的地方在於構建數結構 哈夫曼的思維是每次取列表中兩個值最小的合並 合並后的值加入列表
通過使用優先隊列的小根堆結構 可以比較方便的實現
使用pair結構保存節點的值和節點的下標
優先隊列會默認按照pair的first值排序 省去一部分代碼
樹結構創建好后 就很簡單了 從根節點遍歷遞歸即可
代碼:

#include "stdio.h"
#include <queue>
#define x first
#define y second
using namespace std;

typedef pair<int,int> PII;
priority_queue<PII,vector<PII>,greater<PII> >q; //小根堆 
const int N0=1000;
const int inf=10000000;

struct node1{
	int w, lch, rch, parent;
}ht[2*N0];

int n=0, root, WPL=0;

void readData(){
	int i;
	int num[256]={ 0 };
	char ch;
	while( (ch=getchar())!=EOF ){
		num[ch]++;
	}
	
	for( i=0; i<=255; i++ ){
		if( num[i] ){
			n++;
			ht[n].w=num[i];
		}
	}
	
	root=2*n-1;
}

//********************************************************

void create_ht(){
	int i;
	for(i = 1;i <= n;i++){
		PII p = {ht[i].w,i};
		q.push(p);
	}
	
	//每次從優先隊列中取兩個最小值出來
	while(!q.empty() && q.size() > 1){
		auto q1 = q.top();
		q.pop();
		auto q2 = q.top();
		q.pop();
		n++;
		ht[n].w = q1.x + q2.x; //構建節點並添加到優先隊列中 
		ht[n].lch = q1.y;
		ht[n].rch = q2.y;
		q.push({ht[n].w,n});
	} 
	root = n;
}




//========================================================

void doWPL( int root, int high ){
	//********************************************************
	if(ht[root].lch ==0 && ht[root].rch == 0){ //沒有左兒子以及右兒子  說明遞歸到底部  根據公式計算值
		WPL += ht[root].w * (high - 1); //計算值 
		return ;
	}
	
	if(ht[root].lch != 0){ //如果有左兒子 
		doWPL(ht[root].lch,high + 1);
	}
	if(ht[root].rch != 0){ //如果有右兒子 
		doWPL(ht[root].rch,high + 1);
	}
	//========================================================
}

int main(){	
	FILE *fp;
	if((fp=fopen("huffman.in", "r")) != NULL ){
		fclose(fp);  //存在的話,要先把之前打開的文件關掉
		
		freopen("huffman.in", "r", stdin);
		//freopen("huffman.out", "w", stdout);
	}
	
	readData();	
	
	create_ht();
	
	doWPL( root, 1 );
	
	printf("%d\n", WPL);
	
	return 0;
}

最短距離


思路:
Dijkstra算法步驟:

  1. 定義一個dist距離數組 dist[起點] = 0 ,dist[其他點] 全部初始化為 INF
  2. 循環n-1次 每次找未使用的距離最近的點(和1號點的距離) 用該點去更新他能去的邊的距離 即更新dist數組的值
    由於我們要記錄使用狀態 需要一個額外數組記錄使用狀態 (做完才發現給了used數組 ==)

代碼:

#include "stdio.h"
#include<iostream>
#include<algorithm>
#define maxint 10000

using namespace std;
int n,used[31],map[31][31];
bool st[31];
int dist[50]; // dist[n] = 起點到點 n 的最短距離 

void ini( ){
	int i,j;
	scanf("%d", &n);
	for( i=1; i<=n; i++){
		for( j=1; j<=n; j++){
			scanf("%d", &map[i][j]);
			if( map[i][j] == 0 ){
				map[i][j]=maxint;
			}
		}
	}
}

void Dijkstra(){
	//********************************************************
	for(int i = 0;i < 50 ;i++){
		dist[i] = maxint; //其他距離都初始化為理論上的無窮大  
	}
	dist[1] = 0; //起點到起點的距離為0
	int i,j;
	for(i = 0;i < n - 1;i++){  //遍歷 n-1次 
		int t = -1;
		for(j = 1;j <= n;j++){
		    //每次找未使用的距離最近的點
		    if(!st[j] && (t == -1 || dist[t] > dist[j])){
                       t = j;
                    }
		}
		// 根據該點去更新他能去的邊的距離 
		for(j = 1;j <= n;j++){
			//如果是不可達到的點
			//map[t][j] 為 maxint 便不會更新dist[j]的值 
            dist[j]=min(dist[j],dist[t] + map[t][j]);
        }
        //使用該點后記錄狀態為被使用 
        st[t] = true;
	} 
	printf("%d",dist[n]); //根據dist數組的含義 直接輸出dist[n]即可 
	
	//========================================================
}

int main(){
	FILE *fp;
	if((fp=fopen("dist.in", "r")) != NULL ){
		fclose(fp);  //存在的話,要先把之前打開的文件關掉
		
		freopen("dist.in", "r", stdin);
		//freopen("dist.out", "w", stdout);
	}

	ini();

	Dijkstra();
	
	return 0;
}

路徑回溯


思路:
這種回溯問題 大部分都可以通過棧來保存 然后輸出棧即可(做到了逆序輸出)

代碼:

#include "stdio.h"
#include <stack>

using namespace std;
int n, pre[26][2];

char station[26]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

void ini(){
	int i;
	scanf("%d", &n);
	for(i=0; i<n; i++){
		scanf("%d%d", &pre[i][0], &pre[i][1]);
	}
}

void Pathway(){
	//********************************************************
	
	stack<int>s; //定義一個棧 
	int i;
	//由於題目A必是起點 所以直接從B開始循環 即 i = 1開始 
	for(i = 1;i < n;i++){  
		int distance = 0; //距離
		int x = i;
		while(x != 0){ //根據pre數組循環到起點A 並通過棧保存中間的路徑 
			distance += pre[x][1];
			s.push(x);
			x = pre[x][0];
		}
		
		//輸出路徑 起點必是A 我們直接輸出 
		printf("A");
		while(!s.empty()){
			int temp = s.top();
			s.pop();
			printf("-%c",station[temp]);
		}
		
		//路徑輸出完畢輸出距離
		printf(" %d\n",distance); 
	}
	
	
	
	
	
	
	//========================================================
}

int main(){
	FILE *fp;
	if((fp=fopen("DictS.in", "r")) != NULL ){
		fclose(fp);  //存在的話,要先把之前打開的文件關掉
		
		freopen("DictS.in", "r", stdin);
		//freopen("DictS.out", "w", stdout);
	}
	
	ini();
	
	Pathway();
	
	return 0;
}

數據庫查詢


思路:
說白了就是結構體排序 直接為sort自定義排序規則即可實現

代碼:

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define SIZE 100

int n;

struct Grade_table{
	int no_stu;    /* the number of student*/
	char name[20];    /* the name of student*/
	int maths;
	int english;
	int computer;
};

struct Grade_table grade[SIZE];

//自定義排序規則 
bool cmp(Grade_table &a,Grade_table &b){
	//按照學號從小到大排序 即使用 <
	return a.no_stu < b.no_stu; 
}

void ini( ){
	int i;
	scanf("%d",&n);
	for(i=0;i<n;i++){  
		scanf("%d %s %d %d %d",&(grade[i].no_stu),grade[i].name,&(grade[i].maths),&(grade[i].english),&(grade[i].computer));
    }
}

void select2(){
	//********************************************************
	sort(grade,grade + n,cmp);
	
	//遍歷輸出即可
	int i;
	for(i = 0;i < n;i++){
		if(grade[i].computer >= 60 && grade[i].english >= 60 && grade[i].maths >= 60){
			printf("%d,%s,%d,%d,%d\n",grade[i].no_stu,grade[i].name,grade[i].maths,grade[i].english,grade[i].computer);
		}
	} 
	
	
	
	
	
	//========================================================
}

int main(){
	FILE *fp;
	if((fp=fopen("DB.in", "r")) != NULL ){
		fclose(fp);  //存在的話,要先把之前打開的文件關掉
		
		freopen("DB.in", "r", stdin);
		//freopen("DB.out", "w", stdout);
	}
	
	ini();
	
	select2();
	
	return 0;
}

模擬進程調度算法


思路:
還是一題結構體排序問題 只是稍微復雜了點
根據題意我們優先根據進程到達時間從小到大排序
如果兩者時間相同時根據運行時間從小到大排序

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>

using namespace std;
struct Job_type{ 
	int no;  //作業號
	int tb;  //作業開始時間(分)
	int tr;  //運行時間(分)
}x;

Job_type job[36];
int n;

bool cmp(Job_type &a,Job_type &b){
	if(a.tb != b.tb){ //如果時間不同就按照時間排序 
		return a.tb < b.tb;
	}
	else {  //否則按照運行時間排序 
		return a.tr < b.tr;
	}
}

void load(){
	int i,j;
	scanf("%d", &n);
	for( i=0; i<n; i++){
		scanf("%d", &job[i].no);
		scanf("%d", &job[i].tb);
		scanf("%d", &job[i].tr);
	}
	
	printf("輸入作業順序:\n");
	for(i=0;i<n;i++){
		printf("\t%d\t%d\t%d\n",job[i].no,job[i].tb,job[i].tr);
	}
}

void fcfs_sjf(){
	//********************************************************
	
	sort(job,job + n,cmp); //直接進行一個序的排 
	
	//========================================================
	
	printf("FCFSsjf調度結果:\n");
	printf("   開始時間 作業號 到達時間 運行時間 完成時間 等待時間 周轉時間\n");
	
	//********************************************************
	
	//遍歷輸出即可
	int i;
	int time = 0;  //記錄當前時間 
	for(i = 0;i < n;i++){
		Job_type t = job[i]; //節省代碼量。 
		//周轉時間 等於 完成時間 - 到達時間 
		printf("\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",time,t.no,t.tb,t.tr,time + t.tr,time - t.tb,time + t.tr - t.tb);
		
		// 當前時間 加上該進程運行時間
		time += t.tr; 
	} 
	
	
	//========================================================
}

int main(){
	FILE *fp;
	if((fp=fopen("os.in", "r")) != NULL ){
		fclose(fp);  //存在的話,要先把之前打開的文件關掉
		
		freopen("os.in", "r", stdin);
		//freopen("os.out", "w", stdout);
	}

	load();
	
	fcfs_sjf();
	
	return 0;
}

平均分


思路:
輸入沒有給數據長度 我們需要做循環讀取操作
同時題目要求保留整數部分即可 所以不用做四舍五入的特殊操作

代碼:

#include <stdio.h>

void average(){
	//********************************************************
	int i,j,k;
	int len = 0;  //記錄長度
	int sum = 0; //記錄總和 
	int aver = 0; //平均值 
	while(scanf("%d",&i) != EOF){  //循環讀取數據 直到文件末尾 
		sum += i;
		if(i > 100 || i < 0){
			aver = -1;
			break;
		}
		len++;
	} 
	
	if(aver != -1){
		aver = sum / len;
	}
	
	printf("%d",aver);
	//========================================================
}

int main(){
	FILE *fp;
	if((fp=fopen("average.in", "r")) != NULL ){
		fclose(fp);  //存在的話,要先把之前打開的文件關掉
		
		freopen("average.in", "r", stdin);
		//freopen("average.out", "w", stdout);
	}
	
	average();
	
	return 0;
}

字典回溯


思路:
和上面那題回溯完全一致 用棧即可。。

#include "stdio.h"
#include <stack>

using namespace std;
struct dictionary{
	int index;
	char last_char;
}dict[36];

int n;

void ini(){
	int i;
	scanf("%d", &n);
	for(i=0; i<n; i++){
		scanf("%d %c", &dict[i].index, &dict[i].last_char);
	}
}

void OutputWord(){
	//********************************************************
	stack<char> s;  //定義一個棧
	int i;
	for(i = 0;i < n;i++){
		int k = i;
		while(k != -1){
			s.push(dict[k].last_char);
			k = dict[k].index;
		}
		
		while(!s.empty()){
			char c = s.top();
			s.pop();
			printf("%c",c);
		}
		printf("\n");
	} 
	
	
	
	
	
	//========================================================
}

int main(){
	FILE *fp;
	if((fp=fopen("DictS.in", "r")) != NULL ){
		fclose(fp);  //存在的話,要先把之前打開的文件關掉
		
		freopen("DictS.in", "r", stdin);
		freopen("DictS.out", "w", stdout);
	}
	
	ini();
	
	OutputWord();
	
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM