[白駿20056]魔法使いサメと吹雪(JAVA)
49603 ワード
🔰 質問する
白駿20056号:魔法使いサメと火の嵐
💡 方法
微生物隔離の問題のように
オブジェクトリストを管理するArrayListとオブジェクトは、移動後に地図上に配置する2 Dタイリングマップを設定します.
表示するオブジェクトがあるとしたら
ArrayList<FireBall> list;
ArrayList<FireBall> map[][];
2種類作る.火球オブジェクトリストに保存->listの火球移動(r,c更新)->火球を移動した火球マップに配置->mapの火球状態レポート1つの空間に2つ以上の火球があり、開く->すべての処理が完了したらlistに火球を入れます
これは流れを導く問題である.
ArrayListを二次元配列として使用するのは不思議な問題である.
💦 ミス
ArrayList 2 D配列宣言と割当て
ArrayList<FireBall> map = new ArrayList[N][N];
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
map[i][j] = new ArrayList<FireBall>();
}
}
理解を誤る
一つの部屋に複数の火の玉が四つに分かれているそうです.現在のセルを基準(0,2,4,6)or(1,3,5,7)方向に伝播していると勘違いしています.
これでしばらくシャベルを引いた.問題をよく読みなさい!!
火球移動実施
1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과 연결되어 있다.
この部分を実施する際、実施が不適切であるためindex out error//파이어볼 이동
//기존(index out of error 발생)
cur.r = (cur.r + dx[cur.d] * cur.s + N) % N;
cur.c = (cur.c + dy[cur.d] * cur.s + N) % N;
//정답
cur.r = (cur.r + N + dx[cur.d] * (cur.s % N)) % N;
cur.c = (cur.c + N + dy[cur.d] * (cur.s % N)) % N;
誤った既存のコードが使用されている場合、速度の値(cur.s)は非常に大きく、x、yの移動量(dx、dy)が負の値である場合、cur.r値は負数であってもよい.上記の式では、
cur.r = 0, dx = -1, cur.s = 7 N = 4
と仮定して計算すると、以下のような誤った既存の式が負数となる.System.out.println((0 + (-1) * 7 + 4) % 4); // -3
System.out.println((0 + 4 + (-1) * (7 % 4)) % 4); // 1
すべての方向が穴なのか偶数なのかを実現します。
これはミスではなく、参考にした解答の実現方法が簡単そうなので、よく覚えておいたほうがいいです.
boolean even = 첫번째 요소 %2==0?true : false;
boolean odd = 첫번째 요소 %2 == 1? true : false;
모든 요소 반복
even = even & 현재 요소 %2==0?true:false;
odd = odd & 현재 요소 %2==1?true:false;
반복 끝난 뒤에
even || odd 일 경우, 전부 짝수이거나 전부 홀수 인 것이고
even==false && odd==false이면 짝, 홀 섞여 있는 것이다.
🕑 所要時間
70分
💻 に答える
import java.io.*;
import java.util.*;
public class Main_20056 {
static class FireBall {
int r, c, m, s, d;
public FireBall(int r, int c, int m, int s, int d) {
this.r = r;
this.c = c;
this.m = m;
this.s = s;
this.d = d;
}
}
static int N, M, K;
static int res;
static ArrayList<FireBall> map[][];
static List<FireBall> list;
static int dx[] = { -1, -1, 0, 1, 1, 1, 0, -1 };
static int dy[] = { 0, 1, 1, 1, 0, -1, -1, -1 };
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken()); // 격자 크기
M = Integer.parseInt(st.nextToken()); // 파이어볼 개수
K = Integer.parseInt(st.nextToken()); // 이동 명령 횟수
map = new ArrayList[N][N]; // 파이어볼들 저장하는 격자
for (int i = 0; i < N; i++) { // 격자 초기화
for (int j = 0; j < N; j++) {
map[i][j] = new ArrayList<FireBall>();
}
}
list = new ArrayList<>(); // 파이어볼 리스트
// FireBall 정보 입력받기
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken()) - 1; // (1,1)부터 시작하는 것을 (0,0) 시작으로 바꿈
int c = Integer.parseInt(st.nextToken()) - 1;
int m = Integer.parseInt(st.nextToken());
int s = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
list.add(new FireBall(r, c, m, s, d));
}
simulation(); // 시뮬레이션 시작
res = getResult(); // 남아있는 파이어볼 질량 합 구하기
System.out.println(res);
}
private static int getResult() {
int sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += list.get(i).m;
}
return sum;
}
private static void simulation() {
for (int time = 0; time < K; time++) { // K번동안 명령
// 1. 파이어볼 이동
for (int i = 0; i < list.size(); i++) {
FireBall cur = list.get(i);
// r, c 이동
cur.r = (cur.r + N + dx[cur.d] * (cur.s % N)) % N;
cur.c = (cur.c + N + dy[cur.d] * (cur.s % N)) % N;
map[cur.r][cur.c].add(cur); // 이동후 map에 배치
}
// 2. 이동끝난 후 2개 이상의 파이어볼 있는 칸 체크
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j].size() > 1) {
divide4(i, j);
}
}
}
// map에 배치한거 list에 담기
list.clear();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j].size() != 0) {
for (int k = 0; k < map[i][j].size(); k++) {
FireBall cur = map[i][j].get(k);
list.add(cur);
}
}
}
}
// map 내용들 list에 다 담았으면, 다음 턴을 위해 map clear
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (map[i][j].size() > 0)
map[i][j].clear();
}
}
}
}
private static void divide4(int x, int y) { // 4방향으로 나눠지기
int sumM = 0, sumS = 0; // 질량합, 속력합
boolean flag = true; // 방향 전부 홀,짝이면 true, 아니면 false
for (int i = 0; i < map[x][y].size(); i++) {
FireBall cur = map[x][y].get(i);
sumM += cur.m;
sumS += cur.s;
if (i != map[x][y].size() - 1) {
FireBall next = map[x][y].get(i + 1);
if (cur.d % 2 != next.d % 2) // 홀, 짝 섞여있을 경우 flag=false
flag = false;
}
}
int newM = 0, newS = 0;
newM = sumM / 5;
newS = sumS / map[x][y].size();
map[x][y].clear();
setMap(newM, newS, flag, x, y);
}
private static void setMap(int newM, int newS, boolean flag, int x, int y) {
if (newM != 0) { // 파이어볼 질량 0 아닐때만 살아남으므로
if (flag) {
for (int i = 0; i < 4; i++) {
FireBall newFireBall = new FireBall(x, y, newM, newS, 2 * i);
map[x][y].add(newFireBall);
}
} else {
for (int i = 0; i < 4; i++) {
FireBall newFireBall = new FireBall(x, y, newM, newS, 2 * i + 1);
map[x][y].add(newFireBall);
}
}
}
}
}
🌟 類似型の問題❗解けた良い質問
リファレンス
[Java][Backjun 20056][シミュレーション][サムスンソフトウェア機能テスト]法師サメと火球
Reference
この問題について([白駿20056]魔法使いサメと吹雪(JAVA)), 我々は、より多くの情報をここで見つけました https://velog.io/@bobae1998/백준-20056-마법사-상어와-파이어스톰-JAVAテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol