BOJ 17143

낚시왕

문제출처

문제 해석

낚시왕이 잡은 상어의 크기의 합을 구하는 문제입니다.

1초마다 다음과 같은 일이 반복됩니다.

  1. 낚시왕이 오른쪽으로 한칸 이동합니다.
  2. 낚시왕이 있는 열에 있는 상어 중에서 땅과 제일 가까운 상어를 잡습니다. 잡힌 상어는 맵에서 사라집니다.
  3. 상어가 이동합니다.

설계(10)

낚시왕이 이동할 때마다 상어를 이동시키는 구현문제입니다.

크게 두가지 과정을 거치게 됩니다.

  1. 낚시
    • 각 열마다 행을 기준으로 제일 가까운 상어를 잡고 없앱니다.
  2. 상어 이동
    • 모든 맵을 탐색해서 상어가 있는 위치마다 각각 이동을 시킵니다.
    • 편의성을 위해서 copy_arr배열을 사용합니다. arr배열을 초기화 후, copy_arr배열을 기반으로 상어를 이동시킨 후, arr에 저장하는 방식으로 진행합니다.
    • 이동을 시키고나서 해당 arr에 저장된 상어의 크기보다 큰 경우만 갱신하도록 합니다.

각 상어의 속도가 (s<=1000)이므로 시간복잡도를 계산하면 최악의 경우에 O(NxM^2xs)=10^9이므로 시간초과가 날 것입니다.

s의 값으로 인해 맵을 여러번 도는 것을 방지하기 위해서 나머지 값을 이용합니다.

구현(40)

코드
#include <iostream>
#include <cstring>
using namespace std;

#define MAXN 100

int dx[] = {-1,1,0,0};
int dy[] = {0,0,1,-1};

struct node{
    int s,d,z;
};
node arr[MAXN][MAXN];
node copy_arr[MAXN][MAXN];
int ans;
int N,M,T;
void go(int x, int y, node a){
    int s = a.s;
    int d = a.d;
    int z = a.z;
    if (d <=1) s %= 2*(N-1);
    else s %= 2*(M-1);
    int cnt = s;
    while (cnt--){
        if (x +dx[d] <0 || y+dy[d]<0 || x+dx[d]>=N || y+dy[d]>=M){
            if (d<=1) d= (d+1)%2;
            else d = 2+(d+1)%2;
        }
        x+=dx[d];
        y+=dy[d];
    }
    if (arr[x][y].z < z){
        arr[x][y] = {s,d,z};
    }
}  
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N >> M >> T;
    while (T--){
        int x,y,s,d,z;
        cin >> x >> y >> s >> d >> z;
        x--;
        y--;
        d--;
        arr[x][y] = {s,d,z};
    }
    for (int j = 0; j <M; j++){
        // 상어 낚시
        for (int i = 0 ;i < N; i++){
            if (arr[i][j].z) {
                ans += arr[i][j].z;
                arr[i][j] = {0,0,0};
                break;
            }
        }
        // 상어 이동
        memcpy(copy_arr,arr,sizeof(arr));
        memset(arr,0,sizeof(arr));
        for (int i = 0 ; i <N; i++){
            for (int j= 0;j<M; j++){
                if (copy_arr[i][j].z){
                    go(i,j,copy_arr[i][j]);
                }
            }
        }
    }
    cout << ans <<"\n";
    return 0;
}

디버깅

s를 나머지값으로 갱신할 때, s%=2xN or s%=2xM으로 갱신하는 실수를 하였습니다.

정확히 같은 위치로 되돌아오는 경우는 계산해보면 2x(N-1) or 2x(M-1)이어야 합니다.

제출결과

152 ms

마무리

단순 구현문제였습니다. 그러나, 디버깅에 시간이 오래걸렸습니다.