BOJ 7569 c++ 토마토 - tuple에서 개별 원소 접근은 get<index>(tuple_name) 을 이용. 혹은 tie를 사용하자.

https://www.acmicpc.net/problem/7569

 

tuple로 push한 queue의 원소에서, 해당 원소의 front 값을 받아와서 auto cur= Q.front(); 연산을 거치고 난뒤, 

각각의 해당 원소의 x, y, z 값에 접근하기 위해서는, get<index>(tuple_name) 형태로 접근해서 개별 원소에 접근할 수 있다. 

아래의 풀이는 내가 tuple의 원소에 get<index>(tuple_name) 형태로 접근해서 풀이한 풀이이다. 

#include <bits/stdc++.h>
using namespace std;

int board[105][105][105];
int vis[105][105][105];
int m, n, h;

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

int main(){
  ios::sync_with_stdio(0);
  cin.tie(0);
  
  cin>> m >> n >> h;
  // h먼저 받고, 나머지 m, n 순서로 받도록 하자. 
  for(int k=0; k<h; k++){
    for(int i=0; i<n; i++){
      for(int j=0; j<m; j++){
        cin>>board[k][i][j];
      }
    }
  }
  bool impossilbe=false; 
  for(int k=0; k<h; k++){
    for(int i=0; i<n; i++){
      for(int j=0; j<m; j++){
        if(board[k][i][j]==0){
          impossilbe=true; 
        }
      }
    }
  }
  if(impossilbe==false){
    cout<<0;
    return 0;
  }
  queue<tuple<int,int,int>> Q;
  for(int k=0; k<h; k++){
    for(int i=0; i<n; i++){
      for(int j=0; j<m; j++){
        if(board[k][i][j]==1){
          vis[k][i][j]=1;
          Q.push({k,i,j});
        }
      }
    }
  }
  while(!Q.empty()){
    auto cur=Q.front(); Q.pop();
    for(int dir=0; dir<6; dir++){
      int nx=get<1>(cur)+dx[dir];
      int ny=get<2>(cur)+dy[dir];
      int nz=get<0>(cur)+dz[dir];
      if(nx<0 || nx>=n || ny<0 || ny>=m || nz<0 || nz>=h) continue;
      if(board[nz][nx][ny]==-1) continue;//비어있다면
      if(vis[nz][nx][ny]!=0) continue;//이미 방문했다면
      vis[nz][nx][ny]=vis[get<0>(cur)][get<1>(cur)][get<2>(cur)]+1;
      Q.push({nz,nx,ny});
      // cout<<"h";
    }
  }
  for(int k=0; k<h; k++){
    for(int i=0; i<n; i++){
      for(int j=0; j<m; j++){
        if(board[k][i][j]==-1) vis[k][i][j]=-1;
      }
    }
  }
  int mx=0;
  for(int k=0; k<h; k++){
    for(int i=0; i<n; i++){
      for(int j=0; j<m; j++){
        if(vis[k][i][j]==0) {
          cout<<"-1";
          return 0;
        }
        mx=max(mx,vis[k][i][j]);
      }
    }
  }
  cout<<mx-1;
}

 

tuple로 선언한 밸류의 개별 원소에 접근하는 방법에 대해서 gpt에서 찾아보면, 두가지 방법에 대한 방법을 얻을 수 있다. 

이때 나는 첫번째 설명해준 get<index>(tuple_name) 방식을 사용하여 풀이하였는데, 오히려 tuple을 사용하는 경우는 tie() 함수를 사용하는 두번째 방법이 더욱 보기 간결해보이고 작성할 분량이 적어서 더 좋은것 같다. pair를 사용하는 방법은 auto cur 형태로 작성해서 first, second 접근을 하도록 하고, tuple을 사용하는 문제의 경우는 tie() 함수를 통해서 언팩킹 해보도록 하자. 

C++에서 `std::tuple` 형태로 정의된 값의 개별 원소에 접근하는 방법은 다음과 같이 할 수 있습니다:

1. **사용할 헤더 파일 포함:** `std::tuple`을 사용하려면 `<tuple>` 헤더 파일을 포함해야 합니다.

2. **tuple 원소에 접근:**
   - `std::get<Index>(myTuple)`: `myTuple`에서 `Index` 위치의 원소에 접근합니다. 
   인덱스는 0부터 시작하며, 컴파일 타임에 결정되어야 합니다.

   - 예를 들어, 다음은 `std::tuple`을 정의하고 각 원소에 접근하는 예제입니다:

   ```cpp
   #include <iostream>
   #include <tuple>

   int main() {
       std::tuple<int, double, std::string> myTuple(42, 3.14, "Hello, World!");

       int intValue = std::get<0>(myTuple);      // 첫 번째 원소에 접근
       double doubleValue = std::get<1>(myTuple); // 두 번째 원소에 접근
       std::string stringValue = std::get<2>(myTuple); // 세 번째 원소에 접근

       std::cout << "First: " << intValue << std::endl;
       std::cout << "Second: " << doubleValue << std::endl;
       std::cout << "Third: " << stringValue << std::endl;

       return 0;
   }
   ```

   위의 예제에서는 `std::get()` 함수를 사용하여 각 원소에 접근합니다. 각 원소의 타입은 
   `std::tuple`을 정의할 때 지정됩니다.

3. **tie() 함수 사용:**
   - `std::tie()` 함수를 사용하여 여러 변수에 동시에 `std::tuple`의 원소를 언패킹할 수도 있습니다. 
   이것은 특히 `std::tuple`을 사용하여 여러 값을 반환하는 경우 유용합니다.

   ```cpp
   #include <iostream>
   #include <tuple>

   std::tuple<int, double, std::string> getValues() {
       return std::make_tuple(42, 3.14, "Hello, World!");
   }

   int main() {
       int intValue;
       double doubleValue;
       std::string stringValue;

       std::tie(intValue, doubleValue, stringValue) = getValues();

       std::cout << "First: " << intValue << std::endl;
       std::cout << "Second: " << doubleValue << std::endl;
       std::cout << "Third: " << stringValue << std::endl;

       return 0;
   }
   ```

   이렇게 하면 `getValues()` 함수가 `std::tuple`을 반환하고, `std::tie()` 함수를 사용하여 
   원소를 변수에 할당할 수 있습니다.

이러한 방법으로 `std::tuple`의 원소에 접근할 수 있습니다.

 

 

아래 첨부할 풀이는, tie 함수를 활용한 풀이이다. 이 풀이의 경우는 tie()를 사용하는 부분도 그렇고, 내가 여러 부분으로 나누어서 삼중for문을 통해 처리하는 과정을 하나의 삼중 for문 내부로 엮어서 처리하는 등의 과정을 통해 전체적인 코드의 길이가 짧다. 

이런식으로 풀이할 수 있도록 코드를 작성해보자. 다만 공간복잡도, 시간복잡도 측면에서는 큰 차이는 없다. 

// Authored by : BueVonHun
// Co-authored by : BaaaaaaaaaaarkingDog
// http://boj.kr/f3877bee8d3c454482dd3229e4246b49
#include <bits/stdc++.h>
using namespace std;

int dx[6] = {0, 0, 1, -1, 0, 0};
int dy[6] = {1, -1, 0, 0, 0, 0};
int dz[6] = {0, 0, 0, 0, 1, -1};
int board[103][103][103];
int dist[103][103][103];
queue<tuple<int, int, int>> Q;
int m, n, h;
int main(void) {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> m >> n >> h;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < n; j++) {
      for (int k = 0; k < m; k++) {
        int tmp;
        cin >> tmp;
        board[j][k][i] = tmp;
        if (tmp == 1) Q.push({j, k, i});
        if (tmp == 0) dist[j][k][i] = -1;
      }
    }
  }

  while (!Q.empty()) {
    auto cur = Q.front();
    Q.pop();
    int curX, curY, curZ;
    tie(curX, curY, curZ) = cur;
    for (int dir = 0; dir < 6; dir++) {
      int nx = curX + dx[dir];
      int ny = curY + dy[dir];
      int nz = curZ + dz[dir];
      if (nx < 0 || nx >= n || ny < 0 || ny >= m || nz < 0 || nz >= h) continue;
      if (dist[nx][ny][nz] >= 0) continue;
      dist[nx][ny][nz] = dist[curX][curY][curZ] + 1;
      Q.push({nx, ny, nz});
    }
  }

  int ans = 0;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < n; j++) {
      for (int k = 0; k < m; k++) {
        if (dist[j][k][i] == -1) {
          cout << -1 << "\n";
          return 0;
        }
        ans = max(ans, dist[j][k][i]);
      }
    }
  }
  cout << ans << "\n";
  return 0;
}
  Comments,     Trackbacks