1、愤怒小鸟
X星球愤怒的小鸟喜欢撞火车!
一根平直的铁轨上两火车间相距 1000 米
两火车 (不妨称A和B) 以时速 10米/秒 相对行驶。
愤怒的小鸟从A车出发,时速50米/秒,撞向B车,
然后返回去撞A车,再返回去撞B车,如此往复…
两火车在相距1米处停车。
问:这期间愤怒的小鸟撞 B 车多少次?
注意:需要提交的是一个整数(表示撞B车的次数),不要填写任何其它内容。
【思路】
- 速度 = 路程 / 时间(v = d / s)。
- 鸟飞行的距离 = 总距离 - 火车行走的路程。
- 50 * t = B - 10 * t。
- t = B / 60。
答案:9
public class Main1 {
// 记录撞击的总次数
static int count = 0;
static double B = 1000;
public static void main(String[] args) {
f(B);
// 若为偶数需要/2,若为奇数/2 + 1
System.out.println(count % 2 == 0 ? count / 2 : count / 2 + 1);
}
static void f(double B) {
count ++;
double t = B / 60;
// 总距离减去火车行走的路程
B -= 20 * t;
if (B < 1) {
return;
}
f(B);
}
}
2、反幻方
我国古籍很早就记载着
2 9 4
7 5 3
6 1 8
这是一个三阶幻方。每行每列以及对角线上的数字相加都相等。
下面考虑一个相反的问题。
可不可以用 1~9 的数字填入九宫格。
使得:每行每列每个对角线上的数字和都互不相等呢?
这应该能做到。
比如:
9 1 2
8 4 3
7 5 6
你的任务是搜索所有的三阶反幻方。并统计出一共有多少种。
旋转或镜像算同一种。
比如:
9 1 2
8 4 3
7 5 6
7 8 9
5 4 1
6 3 2
2 1 9
3 4 8
6 5 7
等都算作同一种情况。
请提交三阶反幻方一共多少种。
这是一个整数,不要填写任何多余内容。
【思路】
- 进行全排列
- 判断行、列、斜线上是否有相等的和
- 若有相等的返回false,否则返回true
答案:3120
import java.util.HashSet;
import java.util.Set;
public class Main2 {
static int n = 9, count = 0;
static int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9};
public static void main(String[] args) {
f(0);
System.out.println(count + " " + count / 4 / 2);
}
static void f(int p) {
if (p == a.length) {
if (check()) {
count ++;
}
return;
}
for (int i = p; i < n; i++) {
swap(i, p);
f(1 + p);
swap(i, p);
}
}
static boolean check() {
Set<Integer> set = new HashSet<Integer>();
set.add(a[0] + a[1] + a[2]);
set.add(a[3] + a[4] + a[5]);
set.add(a[6] + a[7] + a[8]);
set.add(a[0] + a[3] + a[6]);
set.add(a[1] + a[4] + a[7]);
set.add(a[2] + a[5] + a[8]);
set.add(a[0] + a[4] + a[8]);
set.add(a[2] + a[4] + a[6]);
return set.size() == n - 1;
}
static void swap(int i, int p) {
int t = a[i];
a[i] = a[p];
a[p] = t;
}
}
3、打靶
小明参加X星球的打靶比赛。
比赛使用电子感应计分系统。其中有一局,小明得了96分。
这局小明共打了6发子弹,没有脱靶。
但望远镜看过去,只有3个弹孔。
显然,有些子弹准确地穿过了前边的弹孔。
不同环数得分是这样设置的:
1,2,3,5,10,20,25,50
那么小明的6发子弹得分都是多少呢?有哪些可能情况呢?
下面的程序解决了这个问题。
仔细阅读分析代码,填写划线部分缺失的内容。
答案:bu - 1
public class Main3 {
static void f(int[] ta, int[] da, int k, int ho, int bu, int sc) {
if (ho < 0 || bu < 0 || sc < 0)
return;
if (k == ta.length) {
if (ho > 0 || bu > 0 || sc > 0)
return;
for (int i = 0; i < da.length; i++) {
for (int j = 0; j < da[i]; j++)
System.out.print(ta[i] + " ");
}
System.out.println();
return;
}
for (int i = 0; i <= bu; i++) {
da[k] = i;
f(ta, da, k + 1, bu - 1, bu - i, sc - ta[k] * i); // 填空位置
}
da[k] = 0;
}
public static void main(String[] args) {
int[] ta = {1, 2, 3, 5, 10, 20, 25, 50};
int[] da = new int[8];
f(ta, da, 0, 3, 6, 96);
}
}
4、路径之谜
小明冒充X星球的骑士,进入了一个奇怪的城堡。
城堡里边什么都没有,只有方形石头铺成的地面。
假设城堡地面是 n x n 个方格。【如图1.png】所示。
按习俗,骑士要从西北角走到东南角。
可以横向或纵向移动,但不能斜着走,也不能跳跃。
每走到一个新方格,就要向正北方和正西方各射一箭。
(城堡的西墙和北墙内各有 n 个靶子)
同一个方格只允许经过一次。但不必做完所有的方格。
如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?
有时是可以的,比如图1.png中的例子。
本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)
输入:
第一行一个整数N(0<N<20),表示地面有 N x N 个方格
第二行N个整数,空格分开,表示北边的箭靶上的数字(自西向东)
第三行N个整数,空格分开,表示西边的箭靶上的数字(自北向南)
输出:
一行若干个整数,表示骑士路径。
为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号: 0,1,2,3…
比如,图1.png中的方块编号为:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
示例:
用户输入:
4
2 4 3 4
4 3 3 3
程序应该输出:
0 4 5 1 2 3 7 11 10 9 13 14 15
【思路】
- 深度遍历dfs。
- 每走一步就将北边和西边的靶子上的箭数-1。
- 在回溯的时候将靶子上的箭数+1。
- 每走到终点的时候进行判断是否已经射完靶子上的箭。
import java.util.Arrays;
import java.util.Scanner;
public class Main4 {
// 地图数组、靶子数组
static int[][] arr, arr1, path, xy = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
static boolean[][] vis;
static int N;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
sc.nextLine();
// 地图数组
arr = new int[N][N];
// 靶子数组
arr1 = new int[2][N];
// 记录是否经过
vis = new boolean[N][N];
// 记录经过的路径
path = new int[N][N];
int c = 0;
for (int i = 0; i < arr1.length; i++) {
String[] s = sc.nextLine().split(" ");
for (int j = 0; j < N; j++) {
arr1[i][j] = Integer.parseInt(s[j]);
}
}
sc.close();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
arr[i][j] = c ++;
}
}
f();
}
static void f() {
// 从起点开始,且靶子箭的数目大于0
if (arr1[0][0] > 0 && arr1[1][0] > 0) {
// 标记已经过
vis[0][0] = true;
// 北方向靶子数-1
arr1[0][0] -= 1;
// 西方向靶子数-1
arr1[1][0] -= 1;
// 深度遍历
dfs(0, 0);
}
}
static void dfs(int x, int y) {
// 若走到终点
if (x == N - 1 && y == N - 1) {
// 判断靶子是否射完
if (check()) {
for (int i = 0; i < N; i++) {
System.out.println(Arrays.toString(path[i]));
}
System.out.print(arr[0][0] + " ");
// 深度遍历进行打印
dfs1(0, 0);
}
return;
}
// 上下左右走
for (int i = 0; i < xy.length; i++) {
int o = x + xy[i][0];
int p = y + xy[i][1];
// 若没有越界 且 未经过 且 靶子箭的数量不为0
if (o >= 0 && o < N && p >= 0 && p < N && !vis[o][p] && arr1[0][p] > 0 && arr1[1][o] > 0) {
arr1[0][p] -= 1;
arr1[1][o] -= 1;
vis[o][p] = true;
// 记录经过的路径
path[o][p] += path[x][y] + 1;
dfs(o, p);
arr1[0][p] += 1;
arr1[1][o] += 1;
vis[o][p] = false;
// 回溯时将当前路径置为0
path[o][p] = 0;
}
}
}
static boolean check() {
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr1[i].length; j++) {
if (arr1[i][j] != 0) {
return false;
}
}
}
return true;
}
static void dfs1(int x, int y) {
for (int i = 0; i < xy.length; i++) {
int o = x + xy[i][0];
int p = y + xy[i][1];
if (o >= 0 && o < N && p >= 0 && p < N && path[o][p] == path[x][y] + 1) {
System.out.print(arr[o][p] + " ");
dfs1(o, p);
}
}
}
}
5、碱基
待更
6、圆圈舞
待更