蓝桥杯刷题记录(2)

文章目录

    • 问题 1116: IP判断
    • 问题 1431: [蓝桥杯][2014年第五届真题]分糖果
    • 问题 1489: [蓝桥杯][算法提高VIP]乘法运算
    • 问题 1476: [蓝桥杯][基础练习VIP]龟兔赛跑预测
    • 问题 1436: [蓝桥杯][2014年第五届真题]地宫取宝
    • 问题 1469: [蓝桥杯][基础练习VIP]数的读法
    • 问题 1454: [蓝桥杯][历届试题]蚂蚁感冒
    • 问题 1429: [蓝桥杯][2014年第五届真题]兰顿蚂蚁
    • 问题 1426: [蓝桥杯][历届试题]九宫重排

问题 1116: IP判断

题目描述
在基于Internet的程序中,我们常常需要判断一个IP字符串的合法性。
合法的IP是这样的形式:
A.B.C.D
其中A、B、C、D均为位于[0, 255]中的整数。为了简单起见,我们规定这四个整数中不允许有前导零存在,如001这种情况。
现在,请你来完成这个判断程序吧_
输入
输入由多行组成,每行是一个字符串,输入由“End of file”结束。
字符串长度最大为30,且不含空格和不可见字符
输出
对于每一个输入,单独输出一行
如果该字符串是合法的IP,输出Y,否则,输出N
样例输入

1.2.3.4
a.b.c.d
267.43.64.12
12.34.56.bb
210.43.64.129
-123.4.5.6

样例输出

Y
N
N
N
Y
N
结题思路
使用string.split("\.")将字符串进行切割,最后逐个判断
代码

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String string;
		boolean flag;
		int number;
		while (sc.hasNext()) {
			flag = true;
			string = sc.nextLine();
			String[] ipStrings = string.split("\\.");
			for (int i = 0; i < ipStrings.length; i++) {
				try {
					number = Integer.valueOf(ipStrings[i]);
					if (number > 255 || number < 0) {
						flag = false;
						break;
					}
				} catch (Exception e) {
					// TODO: handle exception
					flag = false;
				}
			}
			if (flag) {
				System.out.println('Y');
			} else {
				System.out.println("N");
			}

		}
	}
}

问题 1431: [蓝桥杯][2014年第五届真题]分糖果

题目描述
程序首先读入一个整数N(2< N< 100),表示小朋友的人数。
接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)
输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0 n=0表示输入数据的结束,不做处理。
输出
要求程序输出一个整数,表示老师需要补发的糖果数。
样例输入
3
2 2 4

样例输出
4
结题思路
注意的是 进行操作的时候,是每一轮各个孩子手中的糖果数。
代码

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int number = sc.nextInt();
		int[] children = new int[number];
		for (int i = 0; i < children.length; i++) {
			children[i] = sc.nextInt();
		}
		int[] old = children.clone();
		int count = 0; // 糖果数
		int give = 0;
		boolean flag = true;
		while (true) {
			for (int i = 0; i < children.length; i++) {
				children[i] = children[i] - old[i] / 2;
				children[(i + number - 1) % number] += old[i] / 2;
			}
			for (int i = 0; i < children.length; i++) {
				if (children[i] % 2 != 0) {
					children[i] += 1;
					count += 1;
				}
			}
			old = children.clone();
			for (int i = 1; i < children.length; i++) {
				if (children[i] != children[0]) {
					flag = false;
					break;
				}
				if (i == number - 1) {
					flag = true;
				}
			}
			if (flag) {
				System.out.println(count);
				break;
			}
		}
	}
}

问题 1489: [蓝桥杯][算法提高VIP]乘法运算

题目描述
编制一个乘法运算的程序。
从键盘读入2个100以内的正整数,进行乘法运算并以竖式输出。

样例输入
16 8
样例输出
16
× 8
━━━
128
8×16=128,则第四行128右侧对准个位输出。计算完成,不再输出。

再例如:

输:

87x76
输出:

87
×76
━━━
522
609
━━━
6612
输入

输入只有一行,是两个用空格隔开的数字,均在1~99之间(含1和99)。

输出
输出为4行或7行,符合乘法的竖式运算格式。

注意,乘号和下划线为特殊符号,可以从样例中复制黏贴。
样例输入
5 2
样例输出
5
× 2
━━━
10
结题思路
分b>10,=10,<10三种情况讨论
代码

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int a = sc.nextInt();
		int b = sc.nextInt();
		System.out.printf("%4d\n", a);
		System.out.printf("×%2d\n", b);
		System.out.println("━━━");
		if (b >= 10) {
			int b1 = b % 10;
			if (b1 == 0) {
				System.out.println(" 00");
			} else {
				System.out.printf("%4d\n", a * b1);
			}
			int b2 = b / 10;
			System.out.printf("%3d\n", a * b2);
			System.out.println("━━━");
		}
		System.out.printf("%4d\n", a * b);
	}
}

问题 1476: [蓝桥杯][基础练习VIP]龟兔赛跑预测

题目描述
话说这个世界上有各种各样的兔子和乌龟,但是 研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔 子和乌龟的赛跑。他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先t米或以 上,它们就会停下来休息s秒。对于不同的兔子,t,s的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。

然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1 米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找 到了你——清华大学计算机系的高才生——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。
输入
输入只有一行,包含用空格隔开的五个正整数v1,v2,t,s,l,其中(v1,v2< =100;t< =300;s< =10;l< =10000且为v1,v2的公倍数)
输出
输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。

第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。
样例输入
10 5 5 2 20
样例输出
D
4
结题思路
每一秒都判断一次,如果兔子领先乌龟t米,就开始睡觉,睡醒发现还领先t米,接着睡觉。直到有一方达到终点。
代码

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int v1 = sc.nextInt(); // 兔子的速度
		int v2 = sc.nextInt(); // 乌龟的速度
		int t = sc.nextInt(); // 兔子领先的距离
		int s = sc.nextInt(); // 兔子休息的时间
		int l = sc.nextInt(); // 跑到总长度
		int tu = 0;
		int gui = 0;
		int sleep = 0;
		boolean flag = false;
		for (int i = 1;; i++) {
			// 判断乌龟和兔子之间的距离
			if (!flag && tu - gui >= t) {
				sleep = s;// 兔子休息
				flag = true;
			}
			if (sleep > 0) {
				sleep--;
			} else {
				flag = false;
				tu += v1;
			}

			gui += v2;
			// System.out.println(i+"--"+tu+"--"+gui);
			// 判断是否有人已到终点
			if (tu >= l || gui >= l) {
				if (tu >= l && gui >= l) {
					System.out.println("D");
				} else if (tu < l) {
					System.out.println("T");
				} else {
					System.out.println("R");
				}
				System.out.println(i);
				break;
			}
		}
	}
}

问题 1436: [蓝桥杯][2014年第五届真题]地宫取宝

题目描述
X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。

地宫的入口在左上角,出口在右下角。

小明被带到地宫的入口,国王要求他只能向右或向下行走。

走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。

当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。

请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
输入
输入一行3个整数,用空格分开:n m k (1< =n,m< =50, 1< =k< =12)

接下来有 n 行数据,每行有 m 个整数 Ci (0< =Ci< =12)代表这个格子上的宝物的价值
输出
要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。

样例输入

2 3 2
1 2 3
2 1 5

样例输出
14
结题思路
建立一个数组d[i][j][k][c]表示i行j列,手中共k个物品,价值都低于c元
则d[i][j][k][c]转移方程是:
当前拿这个物品: s1= d[i-1][j][k-1] w[i][j] +d[i][j-1][k-1] w[i][j]
当前可以拿这个物品的条件是(c>a[i][j]&&k>0);
当前不拿物品 : s2= d[i-1][j][k]c+d[i][j-1][k]c
综合 d[i][j][k][c]= (s1+s2)%mod;
注意事项:
- 初始化(i0||j0)的时候d[i][j][k][c]=0;
- 临界条件(i1&&j1)当k!=0或者 k==1且c>a[i][j]的时候设置为1,其他时候0;
- 答案是d[n][m][k][12];
代码

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int m = scanner.nextInt();
		int k = scanner.nextInt();
		Long a = (long) 0, b = (long) 0, sum = (long) 0;
		long[][][][] dp = new long[51][51][13][13]; // n行m列,手中一共k个东西,价值都低于m;
		int[][] map = new int[55][55];
		int number;
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				map[i][j] = scanner.nextInt();
			}
		}

		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++) {
				for (int j2 = 0; j2 < k + 1; j2++)
					for (int l = 0; l < 13; l++) {
						a = b = (long) 0;
						if (i == 1 && j == 1)
							if (j2 == 0 || (j2 == 1 && l > map[i][j])) {
								dp[i][j][j2][l] = 1;
								continue;
							}
						if (j2 != 0 && l > map[i][j]) {
							a = (long) (dp[i - 1][j][j2 - 1][map[i][j]] + dp[i][j - 1][j2 - 1][map[i][j]]);
						}
						b = (long) (dp[i - 1][j][j2][l] + dp[i][j - 1][j2][l]);
						dp[i][j][j2][l] = (a + b) % 1000000007;
					}
			}
		System.out.println(dp[n][m][k][12]);
	}
}

问题 1469: [蓝桥杯][基础练习VIP]数的读法

题目描述
Tom教授正在给研究生讲授一门关于基因的课程,有一件事情让他颇为头疼:一条染色体上有成千上万个碱基对,它们从0开始编号,到几百万,几千万,甚至上亿。

比如说,在对学生讲解第1234567009号位置上的碱基时,光看着数字是很难准确的念出来的。

所以,他迫切地需要一个系统,然后当他输入12 3456 7009时,会给出相应的念法:

十二亿三千四百五十六万七千零九

用汉语拼音表示为

shi er yi san qian si bai wu shi liu wan qi qian ling jiu

这样他只需要照着念就可以了。

你的任务是帮他设计这样一个系统:给定一个阿拉伯数字串,你帮他按照中文读写的规范转为汉语拼音字串,相邻的两个音节用一个空格符格开。

注意必须严格按照规范,比如说“10010”读作“yi wan ling yi shi”而不是“yi wan ling shi”,“100000”读作“shi wan”而不是“yi shi wan”,“2000”读作“er qian”而不是“liang qian”。
输入
有一个数字串,数值大小不超过2,000,000,000。
输出
是一个由小写英文字母,逗号和空格组成的字符串,表示该数的英文读法。
样例输入

1234567009

样例输出

shi er yi san qian si bai wu shi liu wan qi qian ling jiu

结题思路
分为亿,万,个三部分考虑,每个部分分别进行解析。其中0为特殊情况,要特殊考虑
代码

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String digit[] = { "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };
		while (in.hasNext()) {
			String n = in.next();
			int cnt = n.length() % 4;
			String tmp[] = { "0000", "000", "00", "0" };
			n = tmp[cnt] + n; // 把输入的数字拼成4的整数倍长度
			String ans = "";
			int nzero = 0; // 记录连续0的个数
			for (int i = 4 - cnt; i < n.length(); i++) {// 4-cnt可定位到输入数字的第一位
				if (n.charAt(i) != '0') {
					// 遇到第一个非零数字,且有多个连续的0,且非零数字不在下一组的第一个位置,只需读出一个0
					if (nzero > 0 && i % 4 != 0)
						ans += "ling ";
					nzero = 0;
					if (i % 4 == 0) // 千位
						ans += digit[n.charAt(i) - '0'] + " qian ";
					else if (i % 4 == 1) // 百位
						ans += digit[n.charAt(i) - '0'] + " bai ";
					else if (i % 4 == 2) // 十位
						ans += digit[n.charAt(i) - '0'] + " shi ";
					else // 个位
						ans += digit[n.charAt(i) - '0'] + " ";
				} else
					nzero++;
				if (n.length() - i == 5 && nzero < 4)// 如果位于万位上且这一组的四个数字不全为0,需要加“wan”
					ans += "wan ";
				else if (n.length() - i == 9)// 如果位于亿位上,需要加“yi”
					ans += "yi ";
			}
			if (ans.indexOf("yi shi") == 0) // "yi shi"开头的话要去掉"yi "
				ans = ans.substring(3, ans.length());
			System.out.println(ans);
		}
		in.close();
	}
}

问题 1454: [蓝桥杯][历届试题]蚂蚁感冒

题目描述
长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。

每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。

当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。

这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。

请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。
输入
第一行输入一个整数n (1 < n < 50), 表示蚂蚁的总数。

接着的一行是n个用空格分开的整数 Xi (-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数 据代表的蚂蚁感冒了。
输出
要求输出1个整数,表示最后感冒蚂蚁的数目。

样例输入

5
-10 8 -20 12 25

样例输出
3
结题思路

  • 当首只蚂蚁向右走,则它右边所有向左蚂蚁都感冒;若它右边有向左蚂蚁感冒,则它左边所有向右蚂蚁都感冒。
  • 当首只蚂蚁向左走,则它左边所有向右蚂蚁都感冒;若它左边有向右蚂蚁感冒,则它右边所有向左蚂蚁都感冒。

代码

import java.util.Scanner;

public class Main {
	public static int ab(int b) { // 返回绝对值
		if (b < 0)
			return -b;
		else
			return b;
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int a = sc.nextInt();
		int sum = 1, c = 0;
		boolean d = false;
		for (int i = 1; i < n; i++) {
			int b = sc.nextInt();
			// 第一种情况:
			if (a > 0) { // 首只蚂蚁向右
				if (ab(b) > a && b < 0) { // 右边所有向左蚂蚁都感冒,有蚂蚁感冒则d变为true
					d = true;
					sum++; // sum:感冒蚂蚁个数
				}
				if (ab(b) < a && b > 0) { // 当右边向左的蚂蚁有感冒(d=true)时,则左边所有向右蚂蚁都感冒,c最后
					c++; // c:左边向右蚂蚁个数 加入sum中;否则都不感冒,c就不用了
				}
			}

			// 第二种情况:
			if (a < 0) { // 首只蚂蚁向左
				if (ab(b) < -a && b > 0) { // 左边所有向右蚂蚁都感冒,有蚂蚁感冒则d变为true
					d = true;
					sum++;
				}
				if (ab(b) > -a && b < 0) { // 当左边向右的蚂蚁有感冒(d=true)时,则右边所有向左蚂蚁都感冒,c最后
					c++; // 加入sum中;否则都不感冒,c就不用了
				}
			}
		}
		if (d) {
			sum = sum + c;
		}
		System.out.println(sum);
		sc.close();

	}

}

问题 1429: [蓝桥杯][2014年第五届真题]兰顿蚂蚁

题目描述
蓝桥杯刷题记录(2)_第1张图片
兰顿蚂蚁,是于1986年,由克里斯·兰顿提出来的,属于细胞自动机的一种。

平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只“蚂蚁”。
蚂蚁的头部朝向为:上下左右其中一方。

蚂蚁的移动规则十分简单:
若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;
若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。

规则虽然简单,蚂蚁的行为却十分复杂。刚刚开始时留下的路线都会有接近对称,像是会重复,但不论起始状态如何,蚂蚁经过漫长的混乱活动后,会开辟出一条规则的“高速公路”。

蚂蚁的路线是很难事先预测的。

你的任务是根据初始状态,用计算机模拟兰顿蚂蚁在第n步行走后所处的位置。
输入
输入数据的第一行是 m n 两个整数(3 < m, n < 100),表示正方形格子的行数和列数。
接下来是 m 行数据。
每行数据为 n 个被空格分开的数字。0 表示白格,1 表示黑格。

接下来是一行数据:x y s k, 其中x y为整数,表示蚂蚁所在行号和列号(行号从上到下增长,列号从左到右增长,都是从0开始编号)。s 是一个大写字母,表示蚂蚁头的朝向,我们约定:上下左右分别用:UDLR表示。k 表示蚂蚁走的步数。
输出
输出数据为一个空格分开的整数 p q, 分别表示蚂蚁在k步后,所处格子的行号和列号。

样例输入

5 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
2 3 L 5

样例输出
1 3
结题思路
找好向左向右与坐标的关系对应即可
代码

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int m = scanner.nextInt();
		int n = scanner.nextInt();
		int[][] state = new int[m][n];
		int[][] di = { { -1, 0 }, { 0, +1 }, { +1, 0 }, { 0, -1 } }; // 代表上下左右
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				state[i][j] = scanner.nextInt();
		int x = scanner.nextInt();
		int y = scanner.nextInt();
		char s = scanner.next().charAt(0); // 方向
		int k = scanner.nextInt();
		int sNumber = 0;
		switch (s) {
		case 'U':
			sNumber = 0;
			break;
		case 'D':
			sNumber = 2;
			break;
		case 'L':
			sNumber = 3;
			break;
		case 'R':
			sNumber = 1;
			break;
		default:
			break;
		}
		for (int i = 0; i < k; i++) {
			if (state[x][y] == 0) {
				sNumber = (sNumber + 3) % 4;
				state[x][y] = 1;
			} else {
				sNumber = (sNumber + 1) % 4; // 转向
				state[x][y] = 0;

			}
			x += di[sNumber][0];
			y += di[sNumber][1];
		}
		System.out.println(x + " " + y);
		scanner.close();
	}
}

问题 1426: [蓝桥杯][历届试题]九宫重排

题目描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
蓝桥杯刷题记录(2)_第2张图片
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入
输入第一行包含九宫的初态,第二行包含九宫的终态。

输出
输出最少的步数,如果不存在方案,则输出-1。

样例输入

123.46758

样例输出
3
结题思路
每种排法用一个字符串存起来,用HashSet进行判重。
利用bfs进行宽度优先探索

代码

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;

public class Main {
	public static String startString;
	public static String endString; // 开始与结束的字符串
	public static int xSpace, ySpace; // 空格的位置
	public static int[][] move = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };// 表示分别向上、下、左、右移动一步
	public static HashSet<String> set = new HashSet<String>();

	static class Move {
		public int x;
		public int y;
		public int step;
		public String tempString; // 目前的状态

		public Move(int x, int y, int step, String tempString) {
			super();
			this.x = x;
			this.y = y;
			this.step = step;
			this.tempString = tempString;
		}
	}

	public static void bfs() {
		int x, y, step; // 存储目前的位置坐标,步数
		for (int i = 0; i < startString.length(); i++) { // 寻找九宫格初始状态空格子的位置
			if (startString.charAt(i) == '.') {
				xSpace = i / 3;
				ySpace = i % 3;
				break;
			}
		}
		ArrayList<Move> list = new ArrayList<Move>();
		list.add(new Move(xSpace, ySpace, 0, startString));
		while (!list.isEmpty()) {
			Move nowMove = list.get(0);
			list.remove(0);
			if (nowMove.tempString.equals(endString)) {
				System.out.println(nowMove.step);
				return;
			}
			for (int i = 0; i < 4; i++) {
				x = nowMove.x + move[i][0];
				y = nowMove.y + move[i][1];
				if (x > 2 || x < 0 || y > 2 || y < 0) {
					continue;
				}
				step = nowMove.step + 1;
				char n = nowMove.tempString.charAt(x * 3 + y); // 获取字符
				String tempNowString = nowMove.tempString;
				tempNowString = tempNowString.replace(n, '-');
				tempNowString = tempNowString.replace('.', n);
				tempNowString = tempNowString.replace('-', '.');
				if (!set.contains(tempNowString)) {
					set.add(tempNowString);
					list.add(new Move(x, y, step, tempNowString));
				}

			}
		}
		System.out.println("-1");
		return;
	}

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		startString = scanner.nextLine();
		endString = scanner.nextLine();
		bfs();
		scanner.close();
	}
}

你可能感兴趣的:(笔记)