蓝桥杯部分题目含答案.docx
《蓝桥杯部分题目含答案.docx》由会员分享,可在线阅读,更多相关《蓝桥杯部分题目含答案.docx(22页珍藏版)》请在冰豆网上搜索。
蓝桥杯部分题目含答案
1、未名湖边的烦恼
关键词:
递归,蓝桥杯,算法
问题描述
每年冬天,北大未名湖上都是滑冰的好地方。
北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。
每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。
现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。
(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)
输入格式
两个整数,表示m和n
输出格式
一个整数,表示队伍的排法的方案数。
样例输入
32
样例输出
5
数据规模和约定
m,n∈[0,18]
#include"iostream"
#include"cstdio"
#include"cmath"
#include"algorithm"
#include"map"
usingnamespacestd;
intf(intm,intn){
if(mif(n==0)return1;
returnf(m,n-1)+f(m-1,n);
}
intmain(){
intm,n;
scanf("%d%d",&m,&n);
intans=f(m,n);
printf("%d\n",ans);
return0;
}
2.标题:
蚂蚁感冒
关键词:
结构体排序,蓝桥杯
【题目描述】
长100厘米的细长直杆子上有n只蚂蚁。
它们的头有的朝左,有的朝右。
每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。
当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。
这些蚂蚁中,有1只蚂蚁感冒了。
并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。
请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。
【数据格式】
第一行输入一个整数n(1接着的一行是n个用空格分开的整数Xi(-100正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。
其中,第一个数据代表的蚂蚁感冒了。
要求输出1个整数,表示最后感冒蚂蚁的数目。
例如,输入:
3
5-28
程序应输出:
1
再例如,输入:
5
-108-201225
程序应输出:
3
资源约定:
峰值内存消耗<256M
CPU消耗<1000ms
请严格按要求输出,不要画蛇添足地打印类似:
“请您输入...”的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:
main函数需要返回0
注意:
只使用ANSIC/ANSIC++标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意:
所有依赖的函数必须明确地在源文件中#include,不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
#include"iostream"
#include"cstdio"
#include"cmath"
#include"algorithm"
#include"map"
#include"vector"
usingnamespacestd;
structlocation{
intdir;
intvalue;
intstate;
};
structlocationloc[55];
boolcmp(structlocationa,structlocationb){
if(a.valuereturntrue;
}else{
returnfalse;
}
}
intmain(){
intn,i,tmp;
scanf("%d",&n);
for(i=0;iscanf("%d",&tmp);
if(i==0)loc[i].state=1;
elseloc[i].state=0;
if(tmp>0){
loc[i].dir=1;
loc[i].value=tmp;
}else{
loc[i].dir=-1;
loc[i].value=-tmp;
}
}
sort(loc,loc+n,cmp);
//for(i=0;iintflag=1;
while(flag){
flag=0;
for(i=0;iif(loc[i].dir==1&&loc[i+1].dir==-1){
loc[i].dir=-1;
loc[i+1].dir=1;
if(loc[i].state==1||loc[i+1].state==1){
loc[i].state=1;
loc[i+1].state=1;
flag=1;
//printf("%d%d\n",loc[i].value,loc[i+1].value);
}
}
}
}
intcount=0;
for(i=0;iif(loc[i].state==1)count++;
}
printf("%d\n",count);
return0;
}
3.地宫取宝
递归,记忆搜索,dfs,蓝桥杯
问题描述
X国王有一个地宫宝库。
是nxm个格子的矩阵。
每个格子放一件宝贝。
每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
输入格式
输入一行3个整数,用空格分开:
nmk(1<=n,m<=50,1<=k<=12)
接下来有n行数据,每行有m个整数Ci(0<=Ci<=12)代表这个格子上的宝物的价值
输出格式
要求输出一个整数,表示正好取k个宝贝的行动方案数。
该数字可能很大,输出它对1000000007取模的结果。
样例输入
222
12
21
样例输出
2
样例输入
232
123
215
样例输出
14
#include"iostream"
#include"cstdio"
#include"cmath"
#include"algorithm"
#include"map"
#include"vector"
#include"cstring"
usingnamespacestd;
#defineN1000000007
inta[55][55];
intd[55][55][15][15];
intn,m,k;
intf(intx,inty,intnum,intmaxValue){
if(d[x][y][num][maxValue+1]!
=-1)returnd[x][y][num][maxValue+1];//记忆搜索
intt=0;
if(x==n-1&&y==m-1){//初始条件
if(a[x][y]>maxValue){
if(num==k||num==k-1)t++;
}else{
if(num==k)t++;
}
d[x][y][num][maxValue+1]=t;
returnt;
}
if(xif(a[x][y]>maxValue){
t+=f(x+1,y,num,maxValue);
t%=N;
t+=f(x+1,y,num+1,a[x][y]);
t%=N;
}else{
t+=f(x+1,y,num,maxValue);
t%=N;
}
}
if(yif(a[x][y]>maxValue){
t+=f(x,y+1,num,maxValue);
t%=N;
t+=f(x,y+1,num+1,a[x][y]);
t%=N;
}else{
t+=f(x,y+1,num,maxValue);
t%=N;
}
}
d[x][y][num][maxValue+1]=t;
returnt;
}
intmain(){
inti,j;
scanf("%d%d%d",&n,&m,&k);
for(i=0;ifor(j=0;jscanf("%d",&a[i][j]);
}
}
memset(d,-1,sizeof(d));
//printf("%d\n",d[0][0][0][0]);
d[0][0][0][0]=f(0,0,0,-1);
printf("%d\n",d[0][0][0][0]);
return0;
}
4、 数字三角形
问题描述
(图3.1-1)示出了一个数字三角形。
请编一个程序计算从顶至底的某处的一条路
径,使该路径所经过的数字的总和最大。
●每一步可沿左斜线向下或右斜线向下走;
●1<三角形行数≤100;
●三角形中的数字为整数0,1,…99;
.
(图3.1-1)
输入格式
文件中首先读到的是三角形的行数。
接下来描述整个三角形
输出格式
最大总和(整数)
样例输入
5
7
38
810
2744
45265
样例输出
30
5、带分数
枚举所有1-9组成的序列,考虑每个序列是否可以。
考虑dfs产生序列
问题描述
100可以表示为带分数的形式:
100=3+69258/714。
还可以表示为:
100=82+3546/197。
注意特征:
带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100有11种表示法。
输入格式
从标准输入读入一个正整数N(N<1000*1000)
输出格式
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:
不要求输出每个表示,只统计有多少表示法!
样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6
#include"iostream"
#include"cstdio"
#include"cmath"
usingnamespacestd;
intN,count=0,t=0;
voidequal(int*a);
intmain(){
inti;
scanf("%d",&N);
inta[10];
a[0]=0;
for(a[1]=1;a[1]<=9;a[1]++){
for(a[2]=1;a[2]<=9;a[2]++){
if(a[2]!
=a[1]){
for(a[3]=1;a[3]<=9;a[3]++){
if(a[3]!
=a[1]&&a[3]!
=a[2]){
for(a[4]=1;a[4]<=9;a[4]++){
if(a[4]!
=a[1]&&a[4]!
=a[2]&&a[4]!
=a[3]){
for(a[5]=1;a[5]<=9;a[5]++){
if(a[5]!
=a[1]&&a[5]!
=a[2]&&a[5]!
=a[3]&&a[5]!
=a[4]){
for(a[6]=1;a[6]<=9;a[6]++){
if(a[6]!
=a[1]&&a[6]!
=a[2]&&a[6]!
=a[3]&&a[6]!
=a[4]&&a[6]!
=a[5]){
for(a[7]=1;a[7]<=9;a[7]++){
if(a[7]!
=a[1]&&a[7]!
=a[2]&&a[7]!
=a[3]&&a[7]!
=a[4]&&a[7]!
=a[5]&&a[7]!
=a[6]){
for(a[8]=1;a[8]<=9;a[8]++){
if(a[8]!
=a[1]&&a[8]!
=a[2]&&a[8]!
=a[3]&&a[8]!
=a[4]&&a[8]!
=a[5]&&a[8]!
=a[6]&&a[8]!
=a[7]){
for(a[9]=1;a[9]<=9;a[9]++){
if(a[9]!
=a[1]&&a[9]!
=a[2]&&a[9]!
=a[3]&&a[9]!
=a[4]&&a[9]!
=a[5]&&a[9]!
=a[6]&&a[9]!
=a[7]&&a[9]!
=a[8]){
//for(i=1;i<=9;i++){
//printf("%d",a[i]);
//}
//printf("\n");
equal(a);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
printf("%d\n",count);
return0;
}
voidequal(int*a){
inti,j,k,b,c,d;
for(i=1;i<=6;i++){
for(j=i+1;j<=8;j++){
d=0;
b=0;
c=0;
for(k=1;k<=i;k++){
//b+=a[k]*pow(10,i-k);
b=b*10+a[k];
}
for(k=i+1;k<=j;k++){
//c+=a[k]*pow(10,j-k);
c=c*10+a[k];
}
for(k=j+1;k<=9;k++){
//d+=a[k]*pow(10,9-k);
d=d*10+a[k];
}
//if(t<10){
//printf("%d+%d/%d\n",b,c,d);
//t++;
//}
if((b+1.0*c/d)==N){
count++;
//printf("%d+%d/%d\n",b,c,d);
}
}
}
}
6、错误票据
读取一行字符串,getline(cin,s),s为string.
问题描述
某涉密单位下发了某种票据,并要在年终全部收回。
每张票据有唯一的ID号。
全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。
因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。
你的任务是通过编程,找出断号的ID和重号的ID。
假设断号不可能发生在最大和最小号。
输入格式
要求程序首先输入一个整数N(N<100)表示后面数据行数。
接着读入N行数据。
每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000),请注意行内和行末可能有多余的空格,你的程序需要能处理这些空格。
每个整数代表一个ID号。
输出格式
要求程序输出1行,含两个整数mn,用空格分隔。
其中,m表示断号ID,n表示重号ID
样例输入1
2
568119
10129
样例输出1
79
样例输入2
6
164178108109180155141159104182179118137184115124125129168196
172189127107112192103131133169158
128102110148139157140195197
185152135106123173122136174191145116151143175120161134162190
149138142146199126165156153193144166170121171132101194187188
113130176154177120117150114183186181100163160167147198111119
样例输出2
105120
#include"cstdio"
#include"string"
#include"iostream"
#include"algorithm"
usingnamespacestd;
strings;
inta[10005];
intmain(){
intN;
scanf("%d",&N);
inti,j,k=0,len,number;
getchar();
for(i=1;i<=N;i++){
getline(cin,s);
//cout<
len=s.length();
number=0;
for(j=0;jif(s[j]==''){
a[k]=number;
number=0;
k++;
j++;
while(s[j]=='')j++;
}else{
number=number*10+s[j]-'0';
if(j==len-1){
a[k]=number;
k++;
}
j++;
}
}
}
//for(i=0;i//printf("%d\n",a[i]);
sort(a,a+k);
intans1,ans2;
for(i=1;i//cout<if(a[i]==a[i-1])ans2=a[i];
if(a[i]==a[i-1]+2)ans1=a[i]-1;
}
printf("%d%d\n",ans1,ans2);
return0;
}
7、连号区间数
问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?
这里所说的连号区间的定义是:
如果区间[L,R]里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入格式
第一行是一个正整数N(1<=N<=50000),表示全排列的规模。
第二行是N个不同的数字Pi(1<=Pi<=N),表示这N个数字的某一全排列。
输出格式
输出一个整数,表示不同连号区间的数目。
样例输入1
4
3241
样例输出1
7
样例输入2
5
34251
样例输出2
9
#include"cstdio"
usingnamespacestd;
inta[50005];
intcount=0;
intmain(){
intN;
scanf("%d",&N);
inti,j;
intmin=50005,max=0;
for(i=0;ifor(i=0;imin=50005;
max=0;
for(j=i;jif(a[j]>max)max=a[j];
if(a[j]if(max-min==j-i)count++;
}
//printf("%d,%d\n",i,count);
}
printf("%d\n",count);
return0;
}
8、买不到的数目
动态规划
问题描述
小明开了一家糖果店。
他别出心裁:
把水果糖包成4颗一包和7颗一包的两种。
糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。
当然有些糖果数目是无法组合出来的,比如要买10颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。
大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数,表示每种包装中糖的颗数(都不多于1000)
输出格式
一个正整数,表示最大不能买到的糖数
样例输入1
47
样例输出1
17
样例输入2
35
样例输出2
7
#include"cstdio"
#include"iostream"
#include"string"
usingnamespacestd;
intflag[1005000];
intdp[1001][1002];
intmain(){
intm,n;
scanf("%d%d",&m,&n);
inti,j;
for(i=0;ifor(j=0;j<=n;j++){
dp[0][j]=j*m;
flag[j*m]=1;
}
for(i=0;i<=m;i++){
dp[i][0]=i*n;
flag[i*n]=1;
}
for(i=1;i<=m;i++){
for(j=1;j<=