• 上机练习九


    导航:复试上机历年真题,题目未搜集全
    十四:2003 十三:2004
    十二:2005 十一:2006
    十:2007 九:2008
    八:2009 七:2012
    六:2013 五:2014
    四:2015 三:2017
    二:2018 一:2019

    九、2008

    1、相约2008

    题目:
    相约 2008:2008 是一个合数,求出此合数最多由多少个最小不同质数和组成,并按要求从小到大输出这些质数。
    思路:
    我觉得这是这几年题目最难的一道,这个题目跟17年的求连续素数的和等于某一值不一样,如果为了满足最多的最小质数和,则需要从右往左遍历贪心求连续的素数和,到最后会发现,无法求得一个方案,结果差1,而如果将1当做最小的素数,填补这个差值,恰好可以满足条件。但是显然1不是素数。

    没有想到求满足最小的质数和,但是可以求出来一种方案。

    • 首先先素数打表
    • 用动态规划求从数组中取出几个数满足某一个和S
    • 再根据条件找出这几个数

    动态规划的过程就是给定一个正整数s, 判断一个数组arr中,是否有一组数字加起来等于s。可以参考传送门:动态规划

    代码:

    #include<stdio.h>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn=2009;
    
    int num=0;
    int p[maxn], prime[maxn];//prime数组用来存放素数 
    
    
    
    
    void primeTable()//素数表 
    {
    	for(int i=2;i<maxn;i++)
    	{
    		if(p[i]==0)//p[i]=0说明i是素数 
    		{
    			prime[num++] = i;//i是素数放入prime数组 
    			for(int j=2*i;j<maxn;j+=i) 
    			{
    				p[j] = 1;//i为素数,则i的倍数都不是素数 
    			}
    		}
    	}
    }
    
    
    
    void dpCreat(int arr[], int n, int S)
    {
    	int dp[n][S+1]={0};
    	
    	//边界条件 
    	for(int i=0;i<n;i++)
    		dp[i][0] = 0;
    	for(int j=0;j<S+1;j++)
    		dp[0][j] = 0;
    	dp[0][arr[0]] = 1;
    	
    	//状态方程 
    	for(int i=1;i<n;i++)
    		for(int j=1;j<S+1;j++)
    		{
    			if(arr[i]>j)
    				dp[i][j] = dp[i-1][j];
    			else if(arr[i]<=j)//选与不选arr[i]只需要满足其一就可 
    			{
    				int a=dp[i-1][j];
    				int b=dp[i-1][j-arr[i]];
    				dp[i][j] = a||b;
    			}	
    		} 
    	
    
    	//查找方案 
    	if(dp[n-1][S]==1)
    	{
    		printf("存在方案:
    ");
    	
    		int i = n-1, k=0;
    		int sol[maxn] = {0};
    		while(i>=0)
    		{
    			if((dp[i][S]==1)&&(dp[i-1][S]==0))
    			{
    				sol[k++] = arr[i];
    				S -= arr[i];
    			}
    			if(S==0)
    				break;
    		 	i--;
    		}
    		int sums = 0;
    		for(int j=0;j<k;j++)
    		{
    			sums += sol[j];
    			printf("%4d ", sol[j]);
    		}
    	}
    	else
    		printf("不存在
    "); 
    		
    }
    
    
    
    int main()
    {
    	int S=2008;
    	primeTable();
    	
    	int sums=0, n=0;
    	for(int i=0;i<num;i++)
    	{
    		sums += prime[i]; 
    		n++;
    		if(sums>=S)
    			break;
    	}
    	
    	dpCreat(prime, n, S);
    	
    	return 0;
    }
    
    
    

    2、二叉树

    题目:
    从键盘接受输入,每个节点所含数据元素均为单字符,要完成:建立一棵二叉链表表示方式存储的二叉排序树,并打印输出对其由大到小遍历结果。测试数据:输入 EFHJBCAGID,符号“@”表示结束字符

    思路:
    二叉排序树的建立,如果要找到一个从大到小遍历的结果,可以先用中序遍历结果存放在一个栈中,然后再逐个弹栈顶元素。或者直接逆中序遍历即可。

    代码:

    #include<stdio.h>
    #include<stack>
    
    using namespace std;
    
    typedef struct BSTNode
    {
    	char data;
    	struct BSTNode *lchild, *rchild;
    }BSTNode, *BSTree;
    
    
    stack<char> st;
    
    
    void insert(BSTree *bst, char ch)
    {
    	if(*bst==NULL)
    	{
    		BSTNode *q;
    		q = new BSTNode;
    		q->lchild = NULL; q->rchild = NULL;
    		q->data = ch;
    		*bst = q;
    	}
    	else
    	{
    		if(ch>(*bst)->data)
    			insert(&((*bst)->rchild), ch);
    		else if(ch<(*bst)->data)
    			insert(&((*bst)->lchild), ch);
    	}
    }
    
    
    void creatBST(BSTree *bst)//创建二叉排序树 
    {
    	char ch;
    	*bst = NULL; 
    	scanf("%c", &ch);
    	while(ch!='@')
    	{
    		insert(bst, ch);
    		scanf("%c", &ch);
    	}
    }
    
    
    void inTravel(BSTree bst)//放在栈中 
    {
    	if(bst!=NULL)
    	{
    		inTravel(bst->lchild);
    		st.push(bst->data);
    //		printf("%c", bst->data);
    		inTravel(bst->rchild);
    	}
    }
    
    
    void reverseTravel(BSTree bst)//直接逆序输出 
    {
    	if(bst!=NULL)
    	{
    		reverseTravel(bst->rchild);
    		printf("%c", bst->data);
    		reverseTravel(bst->lchild);	
    	}	
    } 
    
    
    int main()
    {
    	BSTree bst;
    	bst = new BSTNode;
    	creatBST(&bst);
    	inTravel(bst);
    	
    	while(st.empty()==false)//逐个弹出栈顶元素 
    	{
    		printf("%c", st.top());
    		st.pop();
    	}
    	
    	printf("
    ");
    	reverseTravel(bst);
    	
    	return 0;
    }
    

    3、字符平台

    题目:
    编写程序:求字符串中的最大字符平台。
    一个字符串中的任意一个子序列,若子序列中各字符均相同则被称为字符平台。编程要求:输入任意一字符串 S 时,输出 S 中长度最大的所有字符平台的起始位置以及所含字符,注意字符平台有可能不止一个

    代码:

    #include<stdio.h>
    #include<string.h>
    
    using namespace std;
    
    
    typedef struct plat{
    	char ch;
    	int pos;
    	int n;
    	plat()
    	{
    		pos=0;
    		n=0;
    	}
    }plat;
    
    
    plat p[100];
    int num=0;
    
    
    int main()
    {
    	char str[100];
    	int len;
    	gets(str);
    	len = strlen(str);
    	
    	for(int i=0;i<len;i++)
    	{
    		if(i==0)//第一个字符必当占一个字符平台 
    		{
    			p[num].ch = str[i];
    			p[num].pos = i;
    			p[num].n++;
    		}
    		else//要判断连续的字符是否相同, 
    		{
    			if(str[i]==str[i-1])//如果相同字符平台长度加1
    			{
    				p[num].n++;	
    			}	
    			else//不相同新增一个字符平台
    			{
    				num++;
    				p[num].ch = str[i];
    				p[num].pos = i;
    				p[num].n++;	
    			}
    		}
    	}
    	
    	int k=0;
    	for(int i=0;i<=num;i++)//找出最大的字符平台的长度 
    		if(p[i].n>k)
    			k=p[i].n;
    	
    	
    	for(int i=0;i<=num;i++)
    		if(p[i].n==k)
    			printf("%c %d %d
    ", p[i].ch, p[i].pos, p[i].n);
    	
    	return 0;
    }
    
  • 相关阅读:
    打印沙漏
    秋季学期学习总结
    bzoj1059[ZJOI2007]矩阵游戏 二分图匹配
    bzoj1055[HAOI2008]玩具取名 区间dp
    bzoj1053[HAOI2007]反素数ant
    bzoj1049[HAOI2006]数字序列
    bzoj1046[HAOI2007]上升序列
    bzoj1044[HAOI2008]木棍分割 单调队列优化dp
    bzoj3930[CQOI2015]选数 容斥原理
    bzoj1069 [SCOI2007]最大土地面积 旋转卡壳
  • 原文地址:https://www.cnblogs.com/welan/p/12722264.html
Copyright © 2020-2023  润新知