最近,我遇到了一个有趣的编程难题,该难题中提到了一些很好的曲折。在令我惊讶的问题之下,我只是很想知道在下面的情况下,java中是否有任何相关的解决方案是否可行。
问题陈述: 有一个尺寸为m * n的网格,最初,在该网格的左下角单元格(m-1,0)中存在细菌,而所有其他单元格都为空。每秒之后,网格中的每种细菌会自我分裂,并使相邻(水平,垂直和对角线)细胞中的细菌数增加1并死亡。
在n-1秒后,右下角的细胞(m-1,n-1)中存在多少细菌? 我参考了 https://www.codechef.com/problems/BGH17 但未能提交解决方案 下面是更多问题现场的图片
答案 0 :(得分:0)
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class BacteriaProblem {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Number of Rows: ");
int m = sc.nextInt();
System.out.println("Number of Columns: ");
int n = sc.nextInt();
int[][] input = new int[m][n];
input[m - 1][0] = 1;
Stack<String> stack = new Stack<>();
stack.push(m - 1 + "~" + 0);
reproduce(stack, input, n - 1);
System.out.println("Value at Bottom Right corner after n-1 secs: " + input[m - 1][n - 1]);
}
private static void reproduce(Stack<String> stack, int[][] input, int times) {
//exit condition
if (times < 1) {
return;
}
//bacteria after splitting
List<String> children = new ArrayList<>();
//reproduce all existing bacteria
while (!stack.isEmpty()) {
String[] coordinates = stack.pop().split("~");
int x = Integer.parseInt(coordinates[0]);
int y = Integer.parseInt(coordinates[1]);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (i == 0 && j == 0) continue;
split(input, x + i, y + j, children);
}
}
input[x][y]--;
}
//add all children to stack
for (String coord : children) {
stack.push(coord);
}
//reduce times by 1
reproduce(stack, input, times - 1);
}
private static void split(int[][] input, int x, int y, List<String> children) {
int m = input.length;
int n = input[0].length;
if (x >= 0 && x < m && y >= 0 && y < n) {
input[x][y]++;
children.add(x + "~" + y);
}
}
}
答案 1 :(得分:0)
好吧,我在Online Hackerrank测试中被问到这个问题,当时无法解决。 后来我确实尝试对其进行编码,这是C ++中的解决方案,
long countBacteriasAtBottomRight(int m, int n){
long grid[m][n];
// Set all to 0, and only bottom left to 1
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
grid[i][j] = 0;
}
}
grid[m-1][0] = 1;
// Start the cycle, do it for (n-1) times
int time = n-1;
vector<long> toBeUpdated;
while (time--){
cout << "\n\nTime: " << time;
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
while (grid[i][j] > 0){
grid[i][j]--;
// upper left
if (i > 0 && j > 0){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j-1);
}
// upper
if (i > 0){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j);
}
// upper right
if (i > 0 && j < n-1){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j+1);
}
// left
if (j > 0){
toBeUpdated.push_back(i);
toBeUpdated.push_back(j-1);
}
// bottom left
if (i < m-1 && j > 0){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j-1);
}
// bottom
if (i < m-1){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j);
}
// bottom right
if (i < m-1 && j < n-1){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j+1);
}
// right
if (j < n-1){
toBeUpdated.push_back(i);
toBeUpdated.push_back(j+1);
}
};
}
}
// Update all other cells
for (int k=0; k<toBeUpdated.size(); k+=2){
grid[toBeUpdated[k]][toBeUpdated[k+1]]++;
}
for (int i=0; i<m; i++){
cout << endl;
for (int j=0; j<n; j++)
cout << grid[i][j] << " ";
}
// Clear the temp vector
toBeUpdated.clear();
};
return grid[m-1][n-1];
}
答案 2 :(得分:0)
起始情况仅在最左边的列0中有一个值。我们需要在时间n-1之后知道最右边的列n-1中的情况。这意味着我们只需要查看每列一次:在时间x的列x。在时间x之后,列x发生了什么不再重要。因此,我们从左到右,将上一列中的单元格加起来:
1
1 8
1 7 35
1 6 27 104
1 5 20 70 230
1 4 14 44 133 392
1 3 9 25 69 189 518
1 2 5 12 30 76 196 512
1 1 2 4 9 21 51 127 323 ...
您还将注意到,最后一个单元格的结果仅受前一列中的两个单元格的影响,而在此之前的一个中则受三个单元格的影响,因此计算出例如在n = 9的情况下,您只需要计算该三角形中的值:
1
1 4 14
1 3 9 25 69
1 2 5 12 30 76 196
1 1 2 4 9 21 51 127 323
无论网格有多高,我们只需要向上n / 2(向上舍入)行。因此,我们必须计算的总和为n 2 / 4,如果m 还请注意,我们不必一次存储所有这些值,因为我们从左到右逐列进行。因此,我们只需要一个大小为n / 2的一维数组,并且其中的当前值将像这样进行转换(例如,在上面的示例中从第4列变为第5列): 我们在其中从左到右迭代值,在当前元素的左右添加值,减去一个初始化为0的临时变量,将结果存储在一个临时变量中,然后将其添加到当前元素。 因此,理论上的时间复杂度为O(n 2 )或O(n.m),空间复杂度为O(n)或O(m),以较小者为准。实际上,步数为n 2 / 4,所需空间为n / 2。 我不会讲Java,但这是一个简单的JavaScript代码段,可以轻松翻译: [4, 5, 3, 1] (0) -> 0 + 5 - 0 = 5
[9, 5, 3, 1] (5) -> 9 + 3 - 5 = 7
[9,12, 3, 1] (7) -> 12 + 1 - 7 = 6
[9,12, 9, 1] (6) -> 9 + 0 - 6 = 3
[9,12, 9, 4] (3) -> 4 + 0 - 3 = 1
[9,12, 9, 4, 1] (1) (additional value is always 1)
function bacteria(m, n) {
var sum = [1];
for (var col = 1; col < n; col++) {
var temp = 0;
var height = Math.min(col + 1, n - col, m);
if (height > sum.length) sum.push(0);
for (var row = 0; row < height; row++) {
var left = row > 0 ? sum[row - 1] : 0;
var right = row < sum.length - 1 ? sum[row + 1] : 0;
temp = left + right - temp;
sum[row] += temp;
}
}
return sum[0];
}
document.write(bacteria(9, 9));