上机练习九
导航:复试上机历年真题,题目未搜集全
十四: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("存在方案:\n");
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("不存在\n");
}
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("\n");
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\n", p[i].ch, p[i].pos, p[i].n);
return 0;
}
汇总链接
posted on 2020-04-17 20:24 weilanhanf 阅读(538) 评论(0) 编辑 收藏 举报