【蓝桥杯练习】A组代码填空题13-18------更新中

     【13年A组】

4.题目标题:前缀判断

    如下的代码判断 needle_start指向的串是否为haystack_start指向的串的前缀,如不是,则返回NULL。

    比如:"abcd1234" 就包含了 "abc" 为前缀

//填写完整编译 
#include<iostream>
using namespace std;

char* prefix(char* haystack_start, char* needle_start)
{
	char* haystack = haystack_start;      //母串
	char* needle = needle_start;          //前缀

	
	while(*haystack && *needle){//两个指针都没有越界
        //if(------------------------) return NULL;
		if(*(haystack++)!=*(needle++)) return NULL;        //填空位置
	}
//移动指针,并判断	
	if(*needle) return NULL;
	
	return haystack_start;
}

int main(){
	cout<<prefix("abce","ab1c")<<endl;
	return 0;
}

 

6.标题:逆波兰表达式

    正常的表达式称为中缀表达式,运算符在中间,主要是给人阅读的,机器求解并不方便。

    例如:3 + 5 * (2 + 6) - 1

    而且,常常需要用括号来改变运算次序。

    相反,如果使用逆波兰表达式(前缀表达式)表示,上面的算式则表示为:

    - + 3 * 5 + 2 6 1

    不再需要括号,机器可以用递归的方法很方便地求解。

    为了简便,我们假设:

    1. 只有 + - * 三种运算符
    2. 每个运算数都是一个小于10的非负整数
    
    下面的程序对一个逆波兰表示串进行求值。
    其返回值为一个结构:其中第一元素表示求值结果,第二个元素表示它已解析的字符数。

#include <iostream>
using namespace std;

struct EV
{
	int result;  //计算结果 
	int n;       //消耗掉的字符数 
};

struct EV evaluate(char* x)
{
	struct EV ev = {0,0};
	struct EV v1;
	struct EV v2;

	if(*x==0) return ev;
	
	if(x[0]>='0' && x[0]<='9'){
		ev.result = x[0]-'0';    //字符转数字 ,'1'-'0'=1 
		ev.n = 1;
		return ev;
	}
	//- + 3 * 5 + 2 6 1
	v1 = evaluate(x+1);
	//v2 = _____________________________;  //填空位置
	v2 = evaluate(x+1+v1.n);  //填空位置
	
	if(x[0]=='+') ev.result = v1.result + v2.result;
	if(x[0]=='*') ev.result = v1.result * v2.result;
	if(x[0]=='-') ev.result = v1.result - v2.result;
	ev.n = 1+v1.n+v2.n;

	return ev;
}

int main(){
	string s="-+3*5+261";
	const EV &ev = evaluate((char*)(s.c_str()));
	cout<<ev.result;
	return 0;
}

     【14年A组】

4.标题:史丰收速算

    史丰收速算法的革命性贡献是:从高位算起,预测进位。不需要九九表,彻底颠覆了传统手算!

    速算的核心基础是:1位数乘以多位数的乘法。

    其中,乘以7是最复杂的,就以它为例。

    因为,1/7 是个循环小数:0.142857...,如果多位数超过 142857...,就要进1

    同理,2/7, 3/7, ... 6/7 也都是类似的循环小数,多位数超过 n/7,就要进n

    下面的程序模拟了史丰收速算法中乘以7的运算过程。

    乘以 7 的个位规律是:偶数乘以2,奇数乘以2再加5,都只取个位。

    乘以 7 的进位规律是:
    满 142857... 进1,
    满 285714... 进2,
    满 428571... 进3,
    满 571428... 进4,
    满 714285... 进5,
    满 857142... 进6

    请分析程序流程,填写划线部分缺少的代码。

#include <stdio.h>
#include <cstring>
//计算个位 
int ge_wei(int a)
{
	if(a % 2 == 0)
		return (a * 2) % 10;
	else
		return (a * 2 + 5) % 10;	
}

//计算进位 
int jin_wei(char* p)
{
	char* level[] = {
		"142857",
		"285714",
		"428571",
		"571428",
		"714285",
		"857142"
	};
	
	char buf[7];
	buf[6] = '\0';
	strncpy(buf,p,6);
	
	int i;
	for(i=5; i>=0; i--){
		int r = strcmp(level[i], buf);
		if(r<0) return i+1;
		while(r==0){
			p += 6;
			strncpy(buf,p,6);
			r = strcmp(level[i], buf);
			if(r<0) return i+1;
			//______________________________;  //填空
			if(r>0) return i;			 
		}
	}
	
	return 0;
}

//多位数乘以7
void f(char* s) 
{
	int head = jin_wei(s);
	if(head > 0) printf("%d", head);
	
	char* p = s;
	while(*p){
		int a = (*p-'0');
		int x = (ge_wei(a) + jin_wei(p+1)) % 10;
		printf("%d",x);
		p++;
	}
	
	printf("\n");
}

int main()
{
	f("428571428571");
	f("34553834937543");		
	return 0;
}

5. 标题:锦标赛

   如果要在n个数据中挑选出第一大和第二大的数据(要求输出数据所在位置和值),使用什么方法比较的次数最少?我们可以从体育锦标赛中受到启发。

   如图【1.png】所示,8个选手的锦标赛,先两两捉对比拼,淘汰一半。优胜者再两两比拼...直到决出第一名。

   第一名输出后,只要对黄色标示的位置重新比赛即可。

   下面的代码实现了这个算法(假设数据中没有相同值)。

   代码中需要用一个数组来表示图中的树(注意,这是个满二叉树,不足需要补齐)。它不是存储数据本身,而是存储了数据的下标。   
   
   第一个数据输出后,它所在的位置被标识为-1

     【15年A组】

4.格子中输出

StringInGrid函数会在一个指定大小的格子中打印指定的字符串。
要求字符串在水平、垂直两个方向上都居中。
如果字符串太长,就截断。
如果不能恰好居中,可以稍稍偏左或者偏上一点。

下面的程序实现这个逻辑,请填写划线部分缺少的代码。

//%*s   *表示宽度 

#include <stdio.h>
#include <string.h>

void StringInGrid(int width, int height, const char* s)
{
	int i,k;
	char buf[1000];
	strcpy(buf, s);
	if(strlen(s)>width-2) buf[width-2]=0;
	
	printf("+");
	for(i=0;i<width-2;i++) printf("-");
	printf("+\n");
	
	for(k=1; k<(height-1)/2;k++){
		printf("|");
		for(i=0;i<width-2;i++) printf(" ");
		printf("|\n");
	}
	
	printf("|");
	
	//printf("%*s%s%*s",_____________________________________________);  //填空
	printf("%*s%s%*s",((width-strlen(buf))/2-1)," ", buf, ((width-strlen(buf))/2-1), " ");  //填空
	          
	printf("|\n");
	
	for(k=(height-1)/2+1; k<height-1; k++){
		printf("|");
		for(i=0;i<width-2;i++) printf(" ");
		printf("|\n");
	}	
	
	printf("+");
	for(i=0;i<width-2;i++) printf("-");
	printf("+\n");	
}

int main()
{
	StringInGrid(20,6,"abcd1234");
	return 0;
}

5. 九数组分数

1,2,3...9 这九个数字组成一个分数,其值恰好为1/3,如何组法?

下面的程序实现了该功能,请填写划线部分缺失的代码。

#include <stdio.h>

void test(int x[])
{
	int a = x[0]*1000 + x[1]*100 + x[2]*10 + x[3];
	int b = x[4]*10000 + x[5]*1000 + x[6]*100 + x[7]*10 + x[8];
	
	if(a*3==b) printf("%d / %d\n", a, b);
}

void f(int x[], int k)
{
	int i,t;
	if(k>=9){        //出口,k=9形成一个排列 
		test(x);
		return;
	}
	
	for(i=k; i<9; i++){          //递归 
		{t=x[k]; x[k]=x[i]; x[i]=t;}
		f(x,k+1);
		//_____________________________________________ // 填空处
		{t=x[k]; x[k]=x[i]; x[i]=t;}   //回溯,恢复到下探之前的状态 
	}
}
	
int main()
{
	int x[] = {1,2,3,4,5,6,7,8,9};
	f(x,0);	
	return 0;
}

     【16年A组】

4.排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。

其思想是:先选一个“标尺”,
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。

这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。

下面的代码是一种实现,请分析并填写划线部分缺少的代码。

#include <stdio.h>

void swap(int a[], int i, int j)
{
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}

int partition(int a[], int p, int r)
{
    int i = p;
    int j = r + 1;
    int x = a[p];
    while(1){
        while(i<r && a[++i]<x);
        while(a[--j]>x);
        if(i>=j) break;
        swap(a,i,j);
    }
	//______________________;  填空 
	swap(a,p,j); 
    return j;
}

void quicksort(int a[], int p, int r)
{
    if(p<r){
        int q = partition(a,p,r);
        quicksort(a,p,q-1);
        quicksort(a,q+1,r);
    }
}
    
int main()
{
	int i;
	int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
	int N = 12;
	
	quicksort(a, 0, N-1);
	
	for(i=0; i<N; i++) printf("%d ", a[i]);
	printf("\n");
	
	return 0;
}

 5.消除尾一

下面的代码把一个整数的二进制表示的最右边的连续的1全部变成0
如果最后一位是0,则原数字保持不变。

如果采用代码中的测试数据,应该输出:
00000000000000000000000001100111   00000000000000000000000001100000
00000000000000000000000000001100   00000000000000000000000000001100

请仔细阅读程序,填写划线部分缺少的代码。

#include <stdio.h>

void f(int x)
{
	int i;
	for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
	printf("   ");
	
	//x = _______________________;  填空 
	x = x&(x+1);
	
	for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
	printf("\n");	
}

int main()
{
	f(103);
	f(12);
	return 0;
}

     【17年A组】

5.标题:字母组串

由 A,B,C 这3个字母就可以组成许多串。
比如:"A","AB","ABC","ABA","AACBB" ....

现在,小明正在思考一个问题:
如果每个字母的个数有限定,能组成多少个已知长度的串呢?

他请好朋友来帮忙,很快得到了代码,
解决方案超级简单,然而最重要的部分却语焉不详。

请仔细分析源码,填写划线部分缺少的内容。

#include <stdio.h>

// a个A,b个B,c个C 字母,能组成多少个不同的长度为n的串。
int f(int a, int b, int c, int n)
{
	if(a<0 || b<0 || c<0) return 0;
	if(n==0) return 1; 
	
	//return ______________________________________ ;  // 填空
	return f(a-1,b,c,n-1)+f(a,b-1,c,n-1)+f(a,b,c-1,n-1);
}

int main()
{
	printf("%d\n", f(1,1,1,2));
	printf("%d\n", f(1,2,3,3));
	return 0;
}

6. 标题:最大公共子串

最大公共子串长度问题就是:
求两个串的所有子串中能够匹配上的最大长度是多少。

比如:"abcdkkk" 和 "baabcdadabc",
可以找到的最长的公共子串是"abcd",所以最大公共子串长度为4。

下面的程序是采用矩阵法进行求解的,这对串的规模不大的情况还是比较有效的解法。

请分析该解法的思路,并补全划线部分缺失的代码。

//动态规划 
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std; 
#define N 256
int f(const char* s1, const char* s2)
{
	int a[N][N];
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	int i,j;
	
	memset(a,0,sizeof(int)*N*N);
	int max = 0;          //够匹配上的最大长度
	for(i=1; i<=len1; i++){
		for(j=1; j<=len2; j++){
			if(s1[i-1]==s2[j-1]) {
				//a[i][j] = __________________________;  //填空
				a[i][j] = a[i-1][j-1]+1 ;
				if(a[i][j] > max) max = a[i][j];
			}
		}
	}
	
	return max;
}

int main()
{
	printf("%d\n", f("abcdkkk", "baabcdadabc"));
	return 0;
}

 

     【18年A组】

5.标题:打印图形

如下的程序会在控制台绘制分形图(就是整体与局部自相似的图形)。

当n=1,2,3的时候,输出如下:
请仔细分析程序,并填写划线部分缺少的代码。

 


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

void show(char* buf, int w){
	int i,j;
	for(i=0; i<w; i++){
		for(j=0; j<w; j++){
			printf("%c", buf[i*w+j]==0? ' ' : 'o');
		}
		printf("\n");
	}
}

void draw(char* buf, int w, int x, int y, int size){
	if(size==1){
		buf[y*w+x] = 1;
		return;
	}
	
	//int n = _________________________ ; //填空
	int n=size/3;
	draw(buf, w, x, y, n);
	draw(buf, w, x-n, y ,n);
	draw(buf, w, x+n, y ,n);
	draw(buf, w, x, y-n ,n);
	draw(buf, w, x, y+n ,n);
}

int main()
{
	int N = 3;
	int t = 1;
	int i;
	for(i=0; i<N; i++) t *= 3;
	
	char* buf = (char*)malloc(t*t);
	for(i=0; i<t*t; i++) buf[i] = 0;
	
	draw(buf, t, t/2, t/2, t);
	show(buf, t);
	free(buf);
	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值