第一题:
煤球数目
有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
....
如果一共有100层,共有多少个煤球?
请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:
这个题很好想,找出规律后,循环相加就行。
第一层放1个,第二层3个,第三层6个,第四层10个。
得出规律:array[i]=i+arr[i-1] (从i为1开始)
1 #include<iostream>
2 using namespace std;
3
4 int arr[101];
5
6 int main()
7 {
8 int sum=0;
9 for(int i=1;i<=100;i++){
10 arr[i]=i+arr[i-1];
11 sum+=arr[i];
12 }
13 cout<<sum<<endl;
14 return 0;
15 }
第二题:
生日蜡烛
某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。
现在算起来,他一共吹熄了236根蜡烛。
请问,他从多少岁开始过生日party的?
请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:暴力求解他从几岁开始过生日的,若是他过完这次party刚好吹熄了236根蜡烛,则输出开始的年龄。否则不用判断这次的年龄起始点。
1 #include<iostream> 2 using namespace std; 3 4 int main() 5 { 6 for(int i=1;i<100;i++){ 7 int sum=0; 8 for(int j=i;sum<236;j++){ 9 sum+=j; 10 if(sum==236){ 11 printf("%d ",i); 12 } 13 } 14 } 15 return 0; 16 }
第三题:
凑算式
这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
思路:这个题可以暴力破解,就是遍历1~9,9个数字的全排列,看看哪一个序列满足情况,就记作一次。全排列可以用两种方法实现1、头文件algorithm中的next_permutation()函数遍历全排列。2、使用dfs遍历全排列。
next_permutation()
1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 using namespace std; 5 6 int arr[10]={1,2,3,4,5,6,7,8,9}; 7 8 int main() 9 { 10 int count=0; 11 do{ 12 if(arr[0]+arr[1]*1.0/arr[2]+(arr[3]*100+arr[4]*10+arr[5])*1.0/(arr[6]*100+arr[7]*10+arr[8])==10.0) 13 count++; 14 15 }while(next_permutation(arr,arr+9)); 16 cout<<count<<endl; 17 return 0; 18 }
dfs()方法
1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 using namespace std; 5 int arr[10],Count=0; 6 bool used[10]; 7 8 void dfs(int step) 9 { 10 if(step==9){ 11 if(arr[0]+arr[1]*1.0/arr[2]+(arr[3]*100+arr[4]*10+arr[5])*1.0/(arr[6]*100+arr[7]*10+arr[8])==10.0)Count++; 12 13 } 14 else{ 15 for(int i=1;i<10;i++){ 16 if(!used[i]){ 17 arr[step]=i; 18 used[i]=true; 19 dfs(step+1); 20 used[i]=false; 21 } 22 } 23 } 24 } 25 int main(){ 26 dfs(0); 27 cout<<Count<<endl; 28 return 0; 29 }
第四题:
快速排序
排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。
其思想是:先选一个“标尺”,
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。
这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。
下面的代码是一种实现,请分析并填写划线部分缺少的代码。
注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。
思路:快速排序无论用什么方法,都是要完成确认基准点左边都是比他小的数据,右面的元素都是比它大的数据(升序的情况)。判断好基准点,头脑中模拟一下就能想明白。
1 #include <stdio.h> 2 3 void swap(int a[], int i, int j) 4 { 5 int t = a[i]; 6 a[i] = a[j]; 7 a[j] = t; 8 } 9 10 int partition(int a[], int p, int r) 11 { 12 int i = p; 13 int j = r + 1; 14 int x = a[p]; 15 while(1){ 16 while(i<r && a[++i]<x); 17 while(a[--j]>x); 18 if(i>=j) break; 19 swap(a,i,j); 20 } 21 ___swap(a,j,p)___________________; 22 return j; 23 } 24 25 void quicksort(int a[], int p, int r) 26 { 27 if(p<r){ 28 int q = partition(a,p,r); 29 quicksort(a,p,q-1); 30 quicksort(a,q+1,r); 31 } 32 } 33 34 int main() 35 { 36 int i; 37 int a[] = {5,13,6,24,2,8,19,27,6,12,1,17}; 38 int N = 12; 39 40 quicksort(a, 0, N-1); 41 42 for(i=0; i<N; i++) printf("%d ", a[i]); 43 printf(" "); 44 45 return 0; 46 }
第五题:
抽签
X星球要派出一个5人组成的观察团前往W星。
其中:
A国最多可以派出4人。
B国最多可以派出2人。
C国最多可以派出2人。
....
那么最终派往W星的观察团会有多少种国别的不同组合呢?
下面的程序解决了这个问题。
数组a[] 中既是每个国家可以派出的最多的名额。
程序执行结果为:
DEFFF
CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF
....
(以下省略,总共101行)
1 #include <stdio.h> 2 #define N 6 3 #define M 5 4 #define BUF 1024 5 6 void f(int a[], int k, int m, char b[]) 7 { 8 int i,j; 9 if(k==N){ 10 b[M] = 0; 11 if(m==0) printf("%s ",b); 12 return; 13 } 14 15 for(i=0; i<=a[k]; i++){ 16 for(j=0; j<i; j++) b[M-m+j] = k+'A'; 17 f(a,k+1,m-i,b); //填空位置 18 } 19 } 20 int main() 21 { 22 int a[N] = {4,2,2,1,1,3}; 23 char b[BUF]; 24 f(a,0,M,b); 25 return 0; 26 }
仔细阅读代码,填写划线部分缺少的内容。
注意:不要填写任何已有内容或说明性文字。
思路:k代表哪一个国家提供的人数,m表示总共还需要的人数,i为本次给它分配的人数。
每次递归轮到下一个国家出人。
第六题:
方格填数
如下的10个格子
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:
可以用dfs遍历查看可以满足条件的情况有多少。
这里的L代表行,H代表列。
注意判断好条件:
当前位置是now,判断now位置是否可以,要判断画斜线的单元格相差的绝对值不为1.。
注意判断递归的下一个位置。
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 using namespace std; 5 int arr[5][6],count=0; 6 bool used[10]; 7 8 bool jude(int l,int h,int x) 9 { 10 if(abs(arr[l-1][h-1]-x)==1)return true; 11 if(abs(arr[l-1][h]-x)==1)return true; 12 if(abs(arr[l][h-1]-x)==1)return true; 13 if(abs(arr[l-1][h+1]-x)==1)return true; 14 15 return false; 16 17 } 18 void dfs(int l,int h) 19 { 20 if(l==3&&h==4){ 21 count++; 22 return; 23 } 24 else{ 25 for(int x=0;x<10;x++){ 26 if(!jude(l,h,x)&& !used[x]){ 27 arr[l][h]=x; 28 used[x]=true; 29 if(h<4){ 30 dfs(l,h+1); 31 } 32 else if(h==4){ 33 dfs(l+1,1); 34 35 } 36 used[x]=false; 37 } 38 } 39 } 40 } 41 42 int main() 43 { 44 memset(arr,0x3f,sizeof(arr)); 45 //for(int i=0;i<5;i++)cout<<ends<<arr[0][i]; 46 dfs(1,2); 47 printf("%d ",count); 48 return 0; 49 }
第七题:
剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
图1 图2 图3
这个题刚开始想用dfs做,边判断边选格子,后来觉得这样做不行,错过了很多种情况,主要的原因是探测的方格情况只有一种,一旦回溯过去的路径就再也回不去了,于是参照着网上博友的写法重新又思考了一遍。https://blog.csdn.net/u014552756/article/details/50946197(博友博客),他主要用的方法是先选格子,之后再判断格子是否合法。
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 5 int mp[12]={1,2,3,4,6,7,8,9,11,12,13,14}; 6 int aa[5],vis[5],sum=0; 7 int b[4]={-1,1,-5,5};//左右上下 8 9 void dfs(int n) 10 { 11 for(int i=0;i<4;i++){ 12 int v=aa[n]+b[i]; 13 for(int j=1;j<5;j++){ 14 if(!vis[j]&&v==aa[j]){ 15 vis[j]=true; 16 dfs(j); 17 } 18 } 19 } 20 } 21 22 int main() 23 { 24 int count=0; 25 for(int a=0;a<12;a++) 26 for(int b=a+1;b<12;b++) 27 for(int c=b+1;c<12;c++) 28 for(int d=c+1;d<12;d++) 29 for(int e=d+1;e<12;e++){ 30 aa[0]=mp[a]; 31 aa[1]=mp[b]; 32 aa[2]=mp[c]; 33 aa[3]=mp[d]; 34 aa[4]=mp[e]; 35 memset(vis,0,sizeof(vis)); 36 vis[0]=1; 37 dfs(0); 38 int flag=0; 39 for(int i=0;i<5;i++){ 40 if(!vis[i]){ 41 flag=1; 42 } 43 } 44 if(!flag)count++; 45 46 } 47 cout<<count<<endl; 48 return 0; 49 }
第八题:暂时不会
第九题:
交换瓶子
有N个瓶子,编号 1 ~ N,放在架子上。
比如有5个瓶子:
2 1 3 5 4
要求每次拿起2个瓶子,交换它们的位置。
经过若干次后,使得瓶子的序号为:
1 2 3 4 5
对于这么简单的情况,显然,至少需要交换2次就可以复位。
如果瓶子更多呢?你可以通过编程来解决。
输入格式为两行:
第一行: 一个正整数N(N<10000), 表示瓶子的数目
第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。
输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。
例如,输入:
5
3 1 2 5 4
程序应该输出:
3
再例如,输入:
5
5 4 3 2 1
程序应该输出:
2
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
思路:
1 #include<iostream> 2 using namespace std; 3 4 const int maxn=10000+1000; 5 int main() 6 { 7 int arr[maxn]; 8 int n; 9 scanf("%d",&n); 10 for(int i=0;i<n;i++){ 11 scanf("%d",arr+i); 12 } 13 int ans=0; 14 for(int i=0;i<n-1;i++){ 15 int Min=arr[i],index=i; 16 for(int j=i+1;j<n;j++){ 17 if(Min>arr[j])Min=arr[j],index=j; 18 } 19 if(index!=i){ 20 swap(arr[index],arr[i]); 21 ans++; 22 } 23 } 24 cout<<ans<<endl; 25 return 0; 26 }
第十题:暂时不会