2019年蓝桥杯每周一练题目练习

每周一题之1 3n+1问题
PC/UVa IDs: 110101/100
Popularity: A
Success rate: low Level: 1
测试地址:
https://vjudge.net/problem/UVA-100
[问题描述]
考虑如下的序列生成算法:从整数 n 开始,如果 n 是偶数,把它除以 2;如果 n 是奇数,把它乘 3 加1。用新得到的值重复上述步骤,直到 n = 1 时停止。例如,n = 22 时该算法生成的序列是:
22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1

人们猜想(没有得到证明)对于任意整数 n,该算法总能终止于 n = 1。这个猜想对于至少 1 000 000内的整数都是正确的。

对于给定的 n,该序列的元素(包括 1)个数被称为 n 的循环节长度。在上述例子中,22 的循环节长度为 16。输入两个数 i 和 j,你的任务是计算 i 到 j(包含 i 和 j)之间的整数中,循环节长度的最大值。

[输入]
输入每行包含两个整数 i 和 j。所有整数大于 0,小于 1 000 000。
[输出]

对于每对整数 i 和 j,按原来的顺序输出 i 和 j,然后输出二者之间的整数中的最大循环节长度。这三个整数应该用单个空格隔开,且在同一行输出。对于读入的每一组数据,在输出中应位于单独的一行。
[样例输入]

1 10
100 200
201 210
900 1000

[样例输出]

1 10 20
100 200 125
201 210 89
900 1000 174

注意题目中没有说 也没有告诉 给出的两个数 是按从小到大的顺序给出的 所以我们要长个心眼 不然根本不能编译通过
错解1:

#include <iostream> 
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int arr[10000000];
bool cmp(int a,int b){
	return a > b;
}
void fun(int a,int b){
	int k = 0,temp = 0,j = 0;
	memset(arr,0,sizeof(arr));
	for(int i = a;i <= b;i++){
		k = i;
		temp = 0;
		while(k != 1){
			if(k == 1){
				break;
			}
			if(k % 2 == 0){
				k = k / 2;
			}else{
				k = k * 3 + 1;
			}
			temp++;
		}
		arr[j++] = temp + 1;	
	}
	sort(arr,arr + j,cmp);
}
int main(){
	long long n,m,l = 0;
	while(~scanf("%lld%lld",&n,&m)){
		fun(n,m);
		cout << n << " " << m << " " << arr[0] << endl;
	} 
	return 0;
}

解题思路:

#include <iostream> 
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int maxx;
void fun(int a,int b){
	int k,temp;
	maxx = 0;
	for(int i = min(a, b);i <= max(a, b);i++){
		k = i;
		temp = 1;
		while(k != 1){
			if(k % 2 == 0){
				k = k / 2;
			}else{
				k = k * 3 + 1;
			}
			temp++;
		}
		maxx = max(temp,maxx);	
	}
}
int main(){
	long long n,m,l = 0;
	while(~scanf("%lld%lld",&n,&m)){
		fun(n,m);
		cout << n << " " << m << " " << maxx << endl;
	} 
	return 0;
}

每周一题之2 Mineweep(扫雷)

Minesweeper (扫雷)

PC/UVa IDs: 110102/10189,

Popularity: A,

Success rate: high Level: 1

测试地址:https://vjudge.net/problem/UVA-10189

[问题描述]

Have you ever played Minesweeper? It’s a cute little game which comes within a certain Operating

System which name we can’t really remember. Well, the goal of the game is to find where are all the mines within a M × N field. To help you, the game shows a number in a square which tells you how many mines there are adjacent to that square. For instance, supose the following 4 × 4 field with 2 mines (which are represented by an ‘*’ character):

*…

.*…

If we would represent the same field placing the hint numbers described above, we would end up

with:

*100

2210

1*10

1110

As you may have already noticed, each square may have at most 8 adjacent squares.

[输入]

The input will consist of an arbitrary number of fields. The first line of each field contains two integers

n and m (0 < n, m ≤ 100) which stands for the number of lines and columns of the field respectively.

The next n lines contains exactly m characters and represent the field.

Each safe square is represented by an ‘.’ character (without the quotes) and each mine square

is represented by an ‘*’ character (also without the quotes). The first field line where n = m = 0

represents the end of input and should not be processed.

[输出]

对于每对整数 i 和 j,按原来的顺序输出 i 和 j,然后输出二者之间的整数中的最大循环节长度。这三个整数应该用单个空格隔开,且在同一行输出。对于读入的每一组数据,在输出中应位于单独的一行。

[样例输入]

4 4
*...
....
.*..
....
3 5
**...
.....
.*...
0 0

[样例输出]

Field #1:
*100
2210
1*10
1110
Field #2:
**100
33200
1*100

解题思路1:
大概意思就是遍历每个点的八个方向 如果是雷 就显示雷 (‘*’)用星花表示 如果不是雷 ,就直接遍历这个坐标的八个方向看看是不是雷 显示出这点坐标周围有几个雷
下面的代码提交上去显示答案错误
因为蓝桥杯上的题目描述有些问题,上面全是英文,偏偏到了 输出的时候就变成了中文,本着英语成绩不好 也不想多看 这个英文描述,大概知道什么意思,没有在管题目中的要求,但是所以没有读懂题意,导致一个小问题找了 很久不知道错在哪儿了,系统一直报presentation error错误,百度之后 才知道离正确答案比较近了,时间和空间都满足题意, 就是不知道在哪儿有问题 偏偏蓝桥杯上面的每周一练上面就没有这个题的输出描述 没有 最后在其他博客里面看的 题解 才知道
要注意的是题目要求每两组数据之间用一个空行隔开,所以最后一组数据后面不可以有空行。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char mapp[500][500];
int n,m;
int cross[10] = {0,0,-1,-1,-1,0,1,1,1};
int stra[10] = {0,1,1,0,-1,-1,-1,0,1}; 
int main(){
	cin >> n >> m;
	while(scanf("%d%d",&n,&m) != EOF && n != 0 && m != 0){
		memset(mapp,0,sizeof(mapp));
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				cin >> mapp[i][j];
			}
		}
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				int count = 0;
				if(mapp[i][j] == '*'){
					continue;
				}
				if(mapp[i][j] != '*'){
					for(int k = 0;k <= 8;k++){
						int pre = i + cross[k];
						int pry = j + stra[k];
						if(mapp[pre][pry] == '*'){
							 count++; 
						} 
					}
				}
				mapp[i][j] = count + '0';	
			}
		}
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				cout << mapp[i][j];
			}
			cout << endl;
		}
	}
	return 0; 
} 

正解

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char mapp[500][500];
int n,m;
int cross[10] = {0,0,-1,-1,-1,0,1,1,1};
int stra[10] = {0,1,1,0,-1,-1,-1,0,1}; 
int main(){
	int l = 1;
	cin >> n >> m;
	while(scanf("%d%d",&n,&m) != EOF && n != 0 && m != 0){
		memset(mapp,0,sizeof(mapp));
		if(l != 1){
			cout << endl;
		}
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				cin >> mapp[i][j];
			}
		}
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				int count = 0;
				if(mapp[i][j] == '*'){
					continue;
				}
				if(mapp[i][j] != '*'){
					for(int k = 0;k <= 8;k++){
						int pre = i + cross[k];
						int pry = j + stra[k];
						if(mapp[pre][pry] == '*'){
							 count++; 
						} 
					}
				}
				mapp[i][j] = count + '0';
			}
		}
		printf("Field #%d:\n",l++);
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				cout << mapp[i][j];
			}
			cout << endl;
		}
	}
	return 0; 
} 

3.每周一题之3
[问题描述]
X星球居民小区的楼房全是一样的,并且按矩阵样式排列。其楼房的编号为1,2,3…
当排满一行时,从下一行相邻的楼往反方向排号。
比如:当小区排号宽度为6时,开始情形如下:

1 2 3 4 5 6
12 11 10 9 8 7
13 14 15 …

我们的问题是:已知了两个楼号m和n,需要求出它们之间的最短移动距离(不能斜线方向移动)
输入为3个整数w m n,空格分开,都在1到10000范围内
要求输出一个整数,表示m n 两楼间最短移动距离。

[样例输入]
6 8 2
[样例输出]
4
[样例输入]
4 7 20
[样例输出]
5

解题思路1:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int arr[1000][1000];
int main(){
	int n,m,k,w = 1,temp;
	cin >> k >> m >> n;//6 8 2
	for(int i = 1;i <= 1000;i++){
		if(i % 2 == 1){
			int j;
			for(j = 1;j <= k;j++){
				///if(j % k != 0){
				arr[i][j] = w;
				w = w + 1; 			
			}
			//temp = w; 
		}else{
			for(int p = k;p > 0;p--){
				arr[i][p] = w;
				w += 1;
			}			
		}
	} 
	int startx,starty,endx,endy;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= k;j++){
			if(arr[i][j] == m){
				startx = i;
				starty = j;
			}
			if(arr[i][j] == n){
				endx = i;
				endy = j;
			}
		}
	} 
	cout << abs((startx - endx) + (starty - endy));
	return 0;
}
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
int main(){
	int w, m, n;
	int i, j, k = 1;
	int mi, mj, ni, nj;
	cin >> w >> m >> n;
	int arr[1001][w];
	for (i = 0; i < 1001; i++){
		if ((i + 1) % 2 != 0){
			for (j = 0; j < w; j++){
				arr[i][j] = k + j;
			}
			k = arr[i][j - 1];
		}else{
			int f = 1;
			for (j = w - 1; j >= 0; j--, f++){
				arr[i][j] = k + f;
			}
			k = arr[i][0] + 1;
		}
	}
	for (i = 0; i < 1001; i++){
		for (j = 0; j < w; j++){
			if (arr[i][j] == n){
				ni = i;
				nj = j;
			}
			if (arr[i][j] == m){
				mi = i;
				mj = j;
			}
		}
	}
	int a = abs(mi - ni);
	int b = abs(mj - nj);
	printf("%d\n",a + b);
	return 0;
}

4.每周一题之4高斯日记
本周题目是蓝桥杯第四届省赛AB组第一题(填空题),请评论的同学除了给出答案,还要给出你的思路,特别是如果在竞赛中你会怎么做?
[问题描述]

大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210

后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?

高斯出生于:1777年4月30日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791年12月15日。
高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日。
提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21

解题方法1:
提供一种解题的思路
解题思路2:
编程思路
1)不能用日期API,因为日期API都是从1970-1-1开始计算的。
2)所以我们模拟翻日历的过程来算日期,具体看代码注释。
再来说说这个题的考试特点和应变,之所以让大家按编程题来对待,是因为任何填空题都可以改成编程题。

然而就本题来说,在考场上不要用编程来解决,手算+excel更快些:

1777-4-30是第一天,这年过完,是第x天,

x=1+31+30+31+31+30+31+30+31=155+91=246

1778年365天

1779年365天

1780年366天

  ……

过完1798年共7916天,还差197天

1799年前六个月共181天,还差16天

因此答案为1799-7-16

最后一句:对于蓝桥杯省的填空题,excel是个很好的工具,特别是求和公式。

在这里插入图片描述
解题思路3:

public class W4 {

  public static void main(String[] args) {

    Scanner sc = new Scanner(System.in);

    int x = sc.nextInt();

    int y = 1777;

    int m = 4;

    int d = 30;

    for (int i = 2; i <= x; i++) {

      d++;

      if (m == 2 && ((isLeap(y) && d == 30)||(!isLeap(y) && d == 29))) {
      //闰年的2月的30日等于3月1日,非闰年的2月29日相当于3月1日

        m = 3;

        d = 1;

      } else if (m==12&&d==32) { //12月32日相当于下一年的1月1日
        y++;
        m=1;
        d=1;
      }else if (d == 32 && (m == 1 || m == 3 || m == 5 ||
       m == 7 || m == 8 || m == 10) ) {
      //大月的32日等于次月的1日
        m++;
        d = 1;
      } else if (d == 31 && (m == 4 || m == 6 || m == 9 || m == 11)) {
      //小月的31日等于次月的1日
        m++;
        d = 1;
      }
    }
    System.out.println(y+"-"+m+"-"+d);
  }

  public static boolean isLeap(long year) {
    return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0);
  }

}

每周一题之5 翻煎饼

PC/UVa IDs: 110402/120,
Popularity: B, Success rate:high Level: 2
测试地址:
https://vjudge.net/problem/UVA-120
[问题描述](老师已经为宝宝们翻译好啦)
Stacks and Queues are often considered the bread andbutter of data structures and find use in architecture, parsing,operating systems, and discrete event simulation.Stacks are also important in thetheory of formal languages.
堆栈和队列通常被认为是数据结构的面包和黄油,可用于体系结构、解析,操作系统和离散事件模拟。堆栈在形式语言理论中也很重要。

This problem involves both butter and sustenance inthe form of pancakes rather than bread in addition to a finicky server who flips pancakesaccording to a unique, but complete set of rules.
现在的问题涉及黄油和煎饼(而不是面包),同时还有一个根据唯一但完整的规则来翻煎饼的服务器。
Given a stack of pancakes, you are to write a programthat indicates how the stack can be sorted so that the largest pancake is on the bottom and thesmallest pancake is on the top.
给你一栈的煎饼,请你编写一个程序用于指示这个栈如何被排序以使得最大的煎饼在最下面而最小的煎饼在最上面。
The size of a pancake is given by the pancake’sdiameter.
煎饼的直径将被给出。
All pancakes in a stack have different diameters.
栈中的所有煎饼的直径都不一样。
Sorting a stack is done by a sequence of pancake“flips”.
对栈排序是通过一系列"翻转"来完成的。
A flip consists of inserting a spatula between twopancakes in a stack and flipping (reversing) all the pancakes on thespatula (reversing the sub-stack).
一次翻转的意思是:在两个煎饼之间插入铲子,然后将铲子上面的一堆煎饼整体翻过来。也就是指定一个位置,其上的子栈整体翻转。
A flip is specified by giving the position of thepancake on the bottom of the sub-stack to be flipped (relative to the whole stack).
翻转的位置将会被给出。
The pancake on the bottom of the whole stack hasposition 1
and the pancake on the top of a stack of n pancakeshas position n.
位置是这样定义的:栈底编号为1,栈顶编号为n
A stack is specified by giving the diameter of eachpancake in the stack in the order in which the pancakes appear.
一个栈的煎饼的给出方式,是从上到下给出煎饼的直径。
For example, consider the three stacks of pancakesbelow (in which pancake 8 is the top-most pancake of the left stack):
举例来说,这是三个栈,左边的栈的最上面的煎饼直径为8
8 7 2
4 6 5
6 4 8
7 8 4
5 5 6
2 2 7
The stack on the left can be transformed to the stackin the middle via flip(3). The middle stack can be transformed into the right stack via the commandflip(1).
左侧栈,可在位置3(即直径7)处翻转,得到中间的那个栈,而中间那个栈可在位置1(即直径2)处翻转,得到右侧的栈。
Input(输入)
The input consists of a sequence of stacks ofpancakes. Each stack will consist of between 1 and 30 pancakes and each pancake will have an integerdiameter between 1 and 100. The input is terminated by end-of-file. Each stack is given as a single lineof input with the top pancake on a stack appearing first on a line, the bottom pancake appearing last,and all pancakes separated by a space.

输入由多个煎饼栈组成。每个栈有1到30个煎饼,每个煎饼的直径在1-100之间。以文档结束为输入结束。每个栈,独占一行,从左到右依次代表从栈顶到栈底的煎饼的直径,空格隔开。

Output(输出)
For each stack of pancakes, the output should echo theoriginal stack on one line, followed by some sequence of flips that results in the stack ofpancakes being sorted so that the largest diameter pancake is on the bottom and the smallest on top. For eachstack the sequence of flips should be terminated by a ‘0’ (indicating no more flips necessary). Once astack is sorted, no more flips should be made.
对于每个煎饼栈,输出首先应原样将栈的数据打印成一行。
随后的一行是翻转位置的次序,空格隔开,以0结束。(结束的目标是最大直径在最下面,最小直径在最上面)。
Sample Input
1 2 3 4 5
5 4 3 2 1
5 1 2 3 4
Sample Output
1 2 3 4 5
0
5 4 3 2 1
1 0
5 1 2 3 4
1 2 0
解题思路1:

#include <iostream>
#include <deque>
#include <algorithm>
#include <sstream>
using namespace std;
int main() {
	for(string s; getline(cin,s),cout << s << endl ; cout << 0 << endl ){
		deque<int> que;
		stringstream str(s);
		for(int temp; str >> temp; que.push_front(temp));
		for(deque<int>::iterator i = que.begin(); i != que.end(); ++i){
			deque<int>::iterator imax = max_element(i,que.end());
			if(imax != i){
				reverse(imax, que.end());
				if(que.end() - imax - 1){
					cout << que.end() - imax - 1 << " ";	
				}
				reverse(i, que.end());
				cout << i - que.begin() + 1<< " ";
			}
		}
	}
		return 0;
}
展开阅读全文

没有更多推荐了,返回首页