Skip to content

Commit d5c2800

Browse files
committed
Feat: Tomato Problem Algorithm added
1 parent 37797d1 commit d5c2800

1 file changed

Lines changed: 151 additions & 0 deletions

File tree

posts/tomato/index.md

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
title: "Tomato (トマト)"
3+
description: "BOJ 7576 トマト問題の解説及びStringTokenizerの性能分析"
4+
date: 2026-01-20 16:50:00+09:00
5+
categories:
6+
- Algorithm
7+
tags:
8+
- Java
9+
- BFS
10+
- BOJ
11+
- Algorithm
12+
---
13+
14+
# トマト (Tomato)
15+
16+
- **所要時間**: 30分
17+
- **解法アプローチ**:
18+
19+
```
20+
1. 問題文から「熟したトマトの隣接するトマトも熟していく」という点に着目しました。
21+
2. 入力を受け取る際、値が「1(熟したトマト)」の座標をQueueに追加し、BFS(幅優先探索)を用いて熟していくトマトの日数を計算すればよいと考えました。
22+
```
23+
24+
- **コード**:
25+
26+
```java
27+
import java.io.BufferedReader;
28+
import java.io.IOException;
29+
import java.io.InputStreamReader;
30+
import java.util.LinkedList;
31+
import java.util.Queue;
32+
import java.util.StringTokenizer;
33+
34+
class Main {
35+
public static void main(String[] args) throws IOException {
36+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
37+
38+
StringTokenizer st = new StringTokenizer(br.readLine());
39+
int m = Integer.parseInt(st.nextToken());
40+
int n = Integer.parseInt(st.nextToken());
41+
42+
int[][] arr = new int[n][m];
43+
44+
Queue<int[]> queue = new LinkedList<>();
45+
46+
int[] dx = {-1, 1, 0, 0};
47+
int[] dy = {0, 0, -1, 1};
48+
49+
for (int i = 0; i < n; i++) {
50+
st = new StringTokenizer(br.readLine());
51+
for (int j = 0; j < m; j++) {
52+
arr[i][j] = Integer.parseInt(st.nextToken());
53+
if (arr[i][j] == 1) {
54+
queue.add(new int[]{i, j});
55+
}
56+
}
57+
}
58+
59+
while (!queue.isEmpty()) {
60+
int[] current = queue.poll();
61+
int cx = current[0];
62+
int cy = current[1];
63+
64+
for (int i = 0; i < 4; i++) {
65+
int nx = cx + dx[i];
66+
int ny = cy + dy[i];
67+
68+
if (nx >= 0 && nx < n && ny >= 0 && ny < m && arr[nx][ny] == 0) {
69+
arr[nx][ny] = arr[cx][cy] + 1;
70+
queue.add(new int[]{nx, ny});
71+
}
72+
}
73+
}
74+
75+
int result = 0;
76+
77+
for (int i = 0; i < n; i++) {
78+
for (int j = 0; j < m; j++) {
79+
if (arr[i][j] == 0) {
80+
System.out.println(-1);
81+
return;
82+
}
83+
if (result < arr[i][j]) {
84+
result = arr[i][j];
85+
}
86+
}
87+
}
88+
89+
System.out.println(result - 1);
90+
}
91+
}
92+
```
93+
94+
- **学んだこと**:
95+
- 文字列処理(String)において、`StringTokenizer` の方が演算速度が速いことを確認しました。
96+
- **反省点・改善点**:
97+
- 初期のコードは整理されておらず、冗長な部分が多くありました。
98+
- 一時変数(temp variable)を使用してトマトの日数を計算するなど、不要な演算が含まれていました。
99+
- 条件として「トマトが1であれば熟している」とされていましたが、1以上の値に対する制約が特になかったため、日数の計算を直接 `arr` 配列上で行うように改善しました。
100+
101+
下記のパフォーマンステストコードを作成し、`StringTokenizer` の方が演算速度が速いことを確認しました。
102+
103+
```java
104+
import java.util.StringTokenizer;
105+
106+
class SpeedTest {
107+
public static void main(String[] args) {
108+
int DATA_SIZE = 10_000_000;
109+
System.out.println("Creating Data (" + DATA_SIZE + ")... Wait a moment.");
110+
111+
StringBuilder sb = new StringBuilder();
112+
for (int i = 0; i < DATA_SIZE; i++) {
113+
sb.append(i).append(" ");
114+
}
115+
String inputData = sb.toString();
116+
117+
System.out.println("Complete! Length: " + inputData.length());
118+
System.out.println("--------------------------------------------------");
119+
120+
long startSplit = System.currentTimeMillis();
121+
122+
String[] splitResult = inputData.split(" ");
123+
int sumSplit = 0;
124+
for(String s : splitResult) {
125+
sumSplit += s.length();
126+
}
127+
128+
long endSplit = System.currentTimeMillis();
129+
System.out.println("[String.split] Duration: " + (endSplit - startSplit) + "ms");
130+
131+
long startToken = System.currentTimeMillis();
132+
133+
StringTokenizer st = new StringTokenizer(inputData);
134+
int sumToken = 0;
135+
while(st.hasMoreTokens()) {
136+
String s = st.nextToken();
137+
sumToken += s.length();
138+
}
139+
140+
long endToken = System.currentTimeMillis();
141+
System.out.println("[StringTokenizer] Duration: " + (endToken - startToken) + "ms");
142+
143+
System.out.println("--------------------------------------------------");
144+
System.out.println("Result: StringTokenizer is faster!! It's a figure of how fast StringTokenizer is." +
145+
(double)(endSplit - startSplit) / (endToken - startToken));
146+
}
147+
}
148+
```
149+
150+
---
151+
**問題リンク**: [https://www.acmicpc.net/problem/7576](https://www.acmicpc.net/problem/7576)

0 commit comments

Comments
 (0)