阿里2020.3.23暑期实习笔试
答案借鉴:https://www.nowcoder.com/discuss/389778?type=1
1.一共有n个人,从中选一批人出来组队,再从组队的人中选一个人作为队长,一共有多少种选法。
举例:
输入:2
输出:4
过程:{\(\dot{x_1}\)},{\(\dot{x_2}\)},{\(\dot{x_1}\),\(x_2\)},{\(x_1\),\(\dot{x_2}\)}
解:这个题我用组合做的,即\(=\sum{C_n^i*i}\)
组合的代码:
public static long combination(int m, long n) {
if (m == n)
return 1;
if (m == 0)
return 1;
return combination(m, n - 1) + combination(m - 1, n - 1);
}
但很明显……这种这么硬核的计算方法超时不能用。
然后在牛客上看到别人的分析。
动态规划解法:已知n个人的取法为dp[n]。当求n+1人取法dp[n+1]时,新添加的第n+1人有可取可不取两种状态,但是不当队长,因此这时就有2*dp[n]种方法。然后令第n+1人为队长,剩下的人就有\(2^n\)种取法。可的转移方程状态dp[n+1] = 2*dp[n] + \(2^n\)。
但神奇的是就算找到了这种方法,也ac不了,非要用快速幂去计算\(2^n\)。可以是都是坑了。
public static long countTeamer(long n) {
if (n == 0)
return 0;
long count = 0;
long m = 1000000000 + 7;
count = n * binaryPow(2, n - 1, m);
return count;
}
//这里的递归可以考虑用dp做,毕竟递归也是很耗时的
public static long binaryPow(long a, long n, long m) {
long temp;
if (n == 0)
return 1;
else if (n % 2 == 1) {
temp = a * binaryPow(a, n - 1, m) % m;
} else {
temp = binaryPow(a, n / 2, m);
temp = temp * temp % m;
}
return temp;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
long n = sc.nextLong();
long count = countTeamer(n);
System.out.print(count);
}
}
2.有一组n*m的格子,格子中为‘.’的可通行,为‘#’的为障碍物,为‘S’的是开始点,为‘E’的是结束点,计算从开始到结束最短路径长。
每次只可上下左右一格前进,或使用飞行棋。飞行棋是可以跳跃到当前位置对称位置,即\(x+x'=m-1,y+y'=n-1\).飞行棋最多使用5次。
A:
我自己是用DFS做的,上面引用的答案借鉴区的答案是用BFS做的。图方便我把所有结果都放到array里面再找最小。
但找最小路径的题最好还是BFS做吧。
答案仅参考,而且我怀疑会超时……
public static int minPath(char[][] c, int line, int col) {
ArrayList<Integer> array = new ArrayList<>();
if (c == null || c.length == 0 || c[0].length
== 0)
return -1;
int min = Integer.MAX_VALUE;
int count = 0;
for (int i = 0; i < line; i++) {
for (int j = 0; j < col; j++) {
if (c[i][j] == 'S') {
dfs(c, count, i, j, array, 5);
break;
}
}
}
for (Integer i : array) {
min = Math.min(min, i);
}
return min;
}
private static void dfs(char[][] c, int count, int line, int col, ArrayList<Integer> array, int fx) {
if (c[line][col] == 'E') {
array.add(count);
return;
}
if (line != 0 && c[line - 1][col] != '#') {
c[line][col] = '#';
dfs(c, count + 1, line - 1, col, array, fx);
c[line][col] = '.';
}
if (line != c.length - 1 && c[line + 1][col] != '#') {
c[line][col] = '#';
dfs(c, count + 1, line + 1, col, array, fx);
c[line][col] = '.';
}
if (col != 0 && c[line][col - 1] != '#') {
c[line][col] = '#';
dfs(c, count + 1, line, col - 1, array, fx);
c[line][col] = '.';
}
if (col != c.length - 1 && c[line][col + 1] != '#') {
c[line][col] = '#';
dfs(c, count + 1, line, col + 1, array, fx);
c[line][col] = '.';
}
if (fx > 0 && c[c.length - 1 - line][c[0].length - 1 - col] != '#') {
c[line][col] = '#';
dfs(c, count + 1, c.length - 1 - line, c[0].length - 1 - col, array, fx - 1);
c[line][col] = '.';
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int line = sc.nextInt();
int col = sc.nextInt();
char[][] c = new char[line][col];
for (int i = 0; i < line; i++) {
String s = sc.next();
for (int j = 0; j < line; j++) {
c[i][j] = s.charAt(j);
}
}
sc.close();
// int line = 4;
// int col = 4;
// char[][] c = new char[][]{{'#', 'S', '.', '.'},
// {'E', '#', '.', '.'}, {'.', '.', '.', '.'}, {'.', '.', '.', '.'}};
int minPath = minPath(c, line, col);
System.out.print(minPath);
}