문제링크

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

 

25321번: yo, i herd u liek ternary operators, so..

문제에서 요구하는 수를 $1\, 000\, 000\, 007$로 나눈 나머지를 출력한다.

www.acmicpc.net

풀이

  • 연속한 중첩되지 않은 ?: 쌍의 개수가 n 일 때 해석가능 경우의 수는 catalan(n) 이다
    • ?: ?: ?: -> catalan(3)
  • ? (1) : 과 같은 형태에 대하여 해석가능 경우의 수 는 (1) 해석 가능 경우의 수 ( (1) 안에는 0개 이상의 중첩되지 않은 ?: 쌍 개수)
    • ?:??:?::?:?:?: -> ?:?(?:?:):?:?: -> catalan(4) * catalan(2) -> 28
  • 같은 중첩 레벨에서 ?: 쌍의 연속 한 개수 의 카탈란 수의 곱이 답이 되겠다

 

 

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define ll long long
#define ld long double
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pair<int, int> > vpi;
typedef vector<vector<int>> vvi;
typedef pair<ll, ll> pl;
typedef tuple<ll, ll, ll> t;
typedef vector<ll> vl;
typedef vector<pair<ll, ll>> vpl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
int dr[4] = {0, 0, 1, -1};
int dc[4] = {1, -1, 0, 0};
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  #if !defined(ONLINE_JUDGE)
  freopen("../input.txt", "r", stdin);
  freopen("../output.txt", "w", stdout);
  #endif // ONLINE_JUDGE

  const ll MAX_N = 3e5 + 10;
  const ll MOD = 1e9 + 7;
  vl fact(MAX_N, 1);
  for (int i = 1; i < MAX_N; ++i) {
    fact[i] = i * fact[i - 1] % MOD;
  }
  auto power = [&](ll a, ll b) {
    ll ret = 1;
    while (b) {
      if (b & 1) ret = ret * a % MOD;
      a = a * a % MOD;
      b >>= 1;
    }
    return ret;
  };
  auto inv = [&](ll a) {
    return power(a, MOD - 2);
  };
  auto ncr = [&](ll n, ll r) {
    ll ret = fact[n];
    ll denom = fact[r] * fact[n - r] % MOD;
    ret = ret * inv(denom) % MOD;
    return ret;
  };
  auto catalan = [&](ll n) {
    // Calculate value of 2nCn
    ll c = ncr(2 * n, n);
 
    // return 2nCn/(n+1)
    // return c / (n + 1);
    return c * inv(n + 1) % MOD;
  };

  ll ans = 1;
  stack<char> st;

  string s;
  cin >> s;

  for (int i = 0; i < s.size(); ++i) {
    if (s[i] != '?' && s[i] != ':') continue;

    if (s[i] == ':') {
      if (st.size() && st.top() == ':') {
        ll cnt = 0;
        while (st.size() >= 3) {
          auto prev = st.top(); st.pop();
          auto pprev = st.top();
          if (pprev == '?' && prev == ':') {
            ++cnt;
            st.pop();
          } else {
            st.push(prev);
            break;
          }
        }
        ans = ans * catalan(cnt) % MOD;
      }
    }
    st.push(s[i]);
  }

  ll cnt = 0;
  while (st.size()) {
    auto prev = st.top(); st.pop();
    auto pprev = st.top();
    if (pprev == '?' && prev == ':') {
      ++cnt;
      st.pop();
    } else {
      st.push(prev);
      break;
    }
  }

  ans = ans * catalan(cnt) % MOD;
  cout << ans;
}
728x90

문제링크

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

 

25320번: SCV 체인

첫 번째 줄에 두 개의 정수 $N$과 $M$이 공백으로 구분되어 주어진다. $M$은 데이터베이스에 저장된 블록 동작 기록의 개수이다. $(1\le N\le 100\, 000$; $1\le M\le 2N)$ 이후 $M$줄에 걸쳐 블록 동작 기록이

www.acmicpc.net

풀이

  • i 번째 바닥에 둔 각 블록 숫자 뒤에 체인으로 둘 수 있는 블록들(숫자가 큰) 중 최소 개수를 두는게 최적이다
  • 최소한 i + 1 번 블록 숫자로 둘 수 없는 블록까지 체인으로 둬야한다
  • i, i + 1 블록을 둔 로봇이 같은 로봇이면 그 사이에는 홀수 개의 체인, 다른 로봇이면 짝수 개의 체인을 둘 수 있다
  • 마지막 체인 또는 블록은 B 가 둬야 한다 ( 각각 N 개씩 둬야하고 A 부터 시작하므로)

 

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define ll long long
#define ld long double
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pair<int, int> > vpi;
typedef vector<vector<int>> vvi;
typedef pair<ll, ll> pl;
typedef tuple<ll, ll, ll> t;
typedef vector<ll> vl;
typedef vector<pair<ll, ll>> vpl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
int dr[4] = {0, 0, 1, -1};
int dc[4] = {1, -1, 0, 0};
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  #if !defined(ONLINE_JUDGE)
  freopen("../input.txt", "r", stdin);
  freopen("../output.txt", "w", stdout);
  #endif // ONLINE_JUDGE

  int n, m;
  cin >> n >> m;

  vector<pair<string, int> > v(m);
  set<int> st2;

  set<int> st;

  for (int i = 1; i <= 2 * n; ++i) st.insert(i);

  for (int i = 0; i < m; ++i) {
    string tmp;
    cin >> v[i].first >> tmp >> v[i].second;
    st.erase(v[i].second);
    st2.insert(v[i].second);
  }

  st2.insert(1e9);

  v.push_back({"Z", -1});

  vector<vector<pair<string, int> > > ans(m);
  for (int i = 0; i < m; ++i) {
    int parity = (v[i].first == v[i + 1].first);

    auto it = st.upper_bound(v[i].second);
    if (i != m - 1 && parity && it == st.end()) {
      cout << "NO\n";
      return 0;
    }

    int cnt = 0;
    string cur = (v[i].first == "A") ? "B" : "A";
    
    while (it != st.end() && *it < ( v[i].second == *st2.begin() ? *(next(st2.begin())) : *st2.begin())) {
      ++cnt;
      ans[i].push_back({cur, *it});
      cur = (cur == "A") ? "B" : "A";
      int tmp = *it;
      it++;
      st.erase(tmp);
    }
    st2.erase(v[i].second);

    if (ans[i].size() % 2 != parity) {
      if (st.size() && it == st.end()) {
        cout << "NO\n";
        return 0;
      }
      if (it != st.end()) {
        ans[i].push_back({cur, *it});
        st.erase(it);
      }
    }
  }

  if (st.size()) {
    cout << "NO\n";
    return 0;
  }

  if (ans.back().size()) {
    if (ans.back().back().first != "B") {
      cout << "NO\n";
      return 0;
    }
  } else {
    if (v[m - 1].first != "B") {
      cout << "NO\n";
      return 0;
    }
  }

  cout << "YES\n";
  for (int i = 0; i < m; ++i) {
    cout << v[i].first << " BLOCK " << v[i].second << '\n';
    each(e, ans[i]) {
      cout << e.first << " CHAIN " << e.second << '\n';
    }
  }
}
728x90

문제링크

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

 

25319번: Twitch Plays VIIIbit Explorer

첫 번째 줄에는 던전의 세로 길이 $N$, 가로 길이 $M$, 그리고 아이디의 길이 $\lvert S\rvert$가 공백으로 구분되어 주어진다. $(2\le N,M\le 50$; $1\le\lvert S\rvert\le 1\, 000)$ 두 번째 줄부터 다음 $N$개의 각 줄

www.acmicpc.net

풀이

최단거리로 이동할 필요가 없고 방문했던 지점도 방문해도 되므로 (+ 제일 많이 걸려도 (N+M) * 1000 < 1e6) 

s 문자열 차례대로 최대 강화 횟수 c 만큼 움직이며 아이템 주우면 된다

 

c 구하기

  • s의 각 알파벳마다 floor(던전 알파벳 개수 / s 안에서 알파벳 개수) 의 최댓값

 

주의

  • 마지막에 오른쪽 아래로 이동해야함
  • c 가 0 일 수도 있음(강화안하고 탈출만 함)

 

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define ll long long
#define ld long double
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pair<int, int> > vpi;
typedef vector<vector<int>> vvi;
typedef pair<ll, ll> pl;
typedef tuple<ll, ll, ll> t;
typedef vector<ll> vl;
typedef vector<pair<ll, ll>> vpl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
int dr[4] = {0, 0, 1, -1};
int dc[4] = {1, -1, 0, 0};
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  #if !defined(ONLINE_JUDGE)
  freopen("../input.txt", "r", stdin);
  freopen("../output.txt", "w", stdout);
  #endif // ONLINE_JUDGE

  int n, m, slen;
  cin >> n >> m >> slen;

  vector<vpi> v(26);

  for (int i = 0; i < n; ++i) {
    string tmp;
    cin >> tmp;
    for (int j = 0; j < m; ++j) {
      v[tmp[j] - 'a'].push_back({i, j});
    }
  }
  string s; cin >> s;
  vi cnt(26);
  each(e, s) cnt[e - 'a']++;

  int ansC = 1e9;

  each(e, s) ansC = min(ansC, (int)v[e - 'a'].size() / cnt[e - 'a']);


  string l = "";

  auto move = [&](pi& cur, pi& target) {
      int dr = target.first - cur.first;
      int dc = target.second - cur.second;

      char rc = (dr > 0) ? 'D' : 'U';
      char cc = (dc > 0) ? 'R' : 'L';

      dr = abs(dr);
      dc = abs(dc);

      rep(dr) l += rc;
      rep(dc) l += cc;
  };
  pi cur = {0, 0};

  for (int i = 0; i < ansC; ++i) {
    for (int j = 0; j < s.size(); ++j) {
      pi target;
      target = v[s[j] - 'a'].back();
      v[s[j] - 'a'].pop_back();
      move(cur, target);
      l += 'P';
      cur = target;
    }
  }


  pi tmp = {n - 1, m - 1};
  move(cur, tmp);

  cout << ansC << ' '  << l.size() << '\n';
  cout << l;
}
728x90

문제링크

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

 

25317번: functionx

$x$를 변수로 하는 다항식 $f(x)$가 있다. 처음에 $f(x) =1$이다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. $1$ $a$ $b$: $f(x)$에 $(ax+b)$를 곱한다. $2$ $c$: $f(c)$가 음수라면 -, $0$이라면 0, 양수라

www.acmicpc.net

풀이

다항함수에서 f(c) 의 부호를 결정하는 요소는

  • 최고차항의 계수 부호
  • 최고차항의 지수
  • c 보다 작은 근의 개수

가 있다. 위 세개를 고려해서 부호를 결정하면 되겠다 

 

c 보다 작은 근의 개수를 구하기 위해서 segment tree 를 사용할 수 있겠다

근의 범위가 크므로(+ 정수 값이 아니므로) 대소비교만 알 수 있도록 좌표압축을 해준다.

( PBDS 의 ordered set 을 쓰면 더 간결하게 코드 작성 가능)

 

1 a b 에서 a = 0 인 경우를 주의

 

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define ll long long
#define ld long double
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pair<int, int> > vpi;
typedef vector<vector<int>> vvi;
typedef pair<ll, ll> pll;
typedef tuple<ll, ll, ll> tlll;
typedef vector<ll> vl;
typedef vector<pair<ll, ll>> vpl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
int dr[4] = {0, 0, 1, -1};
int dc[4] = {1, -1, 0, 0};
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  #if !defined(ONLINE_JUDGE)
  freopen("../input.txt", "r", stdin);
  freopen("../output.txt", "w", stdout);
  #endif // ONLINE_JUDGE

  int q;
  cin >> q;
  vector<tuple<ll, ll, ll> > query(q);
  vector<tuple<ll, ll, ll> > queryOrg(q);
  vector<pair<ld, int> > v(q);
  for (int i = 0; i < q; ++i) {
    auto& [a, b, c] = query[i];
    cin >> a;
    if (a == 1) {
      cin >> b >> c;
      if (b == 0) {
        v[i] = {1.0L * 1e30, -1};
      } else {
        v[i] = {-1.0L * c / b,i};
      }
    } else {
      cin >> b;
      v[i] = {b, i};
    }
    queryOrg[i] = query[i];
  }
  sort(all(v));

  ld prev;
  int idx = 1;
  for (int i = 0; i < q; ++i) {
    if (v[i].second == -1) continue;
    auto& [a, b, c] = query[v[i].second];

    if (a == 1) {
      if (b > 0) b = 1;
      else if (b == 0) b = 0;
      else b = -1;

      if (i && abs(prev - v[i].first) > 1e-25) {
        c = ++idx;
      } else {
        c = idx;
      }
    } else {
      if (i && abs(prev - v[i].first) > 1e-25) {
        b = ++idx;
      } else {
        b = idx;
      }
    }
    prev = v[i].first;
  }

  vi t(2 * q);
  auto update = [&](int p, int v) {
    for (t[p += q] = v; p > 1; p >>= 1) t[p >> 1] = t[p] + t[p ^ 1];
  };
  auto sum = [&](int l, int r) {
    int ret = 0;
    for (l += q, r += q; l < r; l >>= 1, r >>= 1) {
      if (l & 1) ret += t[l++];
      if (r & 1) ret += t[--r];
    }
    return ret;
  };

  int x = 0;
  int sign = 0;
  int allzero = false;
  for (int i = 0; i < q; ++i) {
    auto [a, b, c] = query[i];
    if (a == 1) {

      if (b == 0) {
        if (get<2>(queryOrg[i]) == 0) allzero = true;
        else {
          if (get<2>(queryOrg[i]) < 0) sign ^= 1;
        }
      } else {
        if (get<1>(queryOrg[i]) < 0) sign ^= 1;
        ++x;
        update(c, t[q + c] + 1);
      }
    } else {

      if (t[q + b] || allzero) cout << 0 << '\n';
      else cout << (((sign + x + sum(1, b + 1)) % 2 == 1) ? '-' : '+' )<< '\n';
    }
  }
}
728x90

문제링크

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

 

25315번: N수매화검법

화산파의 장로 우경은 새로운 무공 N수매화검법을 창안했다. N수매화검법은 이십사수매화검법을 발전시킨 검법으로 총 $N$개의 베기(검으로 무언가를 베는 동작)로 이루어진다. N수매화검법은 2

www.acmicpc.net

풀이

  • ccw 이용해서 선분 교차 판정 해준다
  • w 가 낮은거 부터 처리하는게 최적이다

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define ll long long
#define ld long double
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pair<int, int> > vpi;
typedef vector<vector<int>> vvi;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pld;
typedef tuple<ll, ll, ll> tlll;
typedef vector<ll> vl;
typedef vector<pair<ll, ll>> vpl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
int dr[4] = {0, 0, 1, -1};
int dc[4] = {1, -1, 0, 0};
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  #if !defined(ONLINE_JUDGE)
  freopen("../input.txt", "r", stdin);
  freopen("../output.txt", "w", stdout);
  #endif // ONLINE_JUDGE
  
  auto ccw = [&](pld& p1, pld& p2, pld& p3) {
    ld s = p1.first * p2.second + p2.first * p3.second + p3.first * p1.second;
    s -= (p1.second * p2.first + p2.second * p3.first + p3.second * p1.first);
    if (s > 0) return 1;
    else if (s == 0) return 0;
    else return -1; 
  };

  auto f = [&](pld& p1, pld& p2, pld& p3, pld& p4) {
    auto p1p2 = ccw(p1, p2, p3) * ccw(p1, p2, p4); 
    auto p3p4 = ccw(p3, p4, p1) * ccw(p3, p4, p2); 

    // one line
    if (p1p2 == 0 && p3p4 == 0) {
      if (p1 > p2) swap(p1, p2);
      if (p3 > p4) swap(p3, p4);
      return p3 <= p2 && p1 <= p4; // intersect?
    }
    return p1p2 <= 0 && p3p4 <= 0;
  };

  int n;
  cin >> n;

  vector<tuple<ll, pld, pld> > line(n);

  for (int i = 0;  i < n; ++i) {
    auto& [a,b,c] = line[i];
    cin >> b.first >> b.second >> c.first >> c.second >> a;
  }
  sort(all(line));

  ll ans = 0;
  FOR(i, 0, n) {
    auto [w1, a, b] = line[i];
    ans += w1;
    FOR(j, i + 1, n) {
      auto [w2, c, d] = line[j];
      if (f(a, b, c, d)) ans += w1;
    }
  }
  cout << ans;
}
728x90

문제링크

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

 

1441번: 나누어 질까

첫째 줄에 A의 크기 N과 L, R이 주어진다. N은 18보다 작거나 같은 자연수이고, L은 1,000,000,000보다 작거나 같은 자연수, R은 L보다 크거나 같고, 1,000,000,000보다 작거나 같은 자연수이다. 둘째 줄에 A

www.acmicpc.net

풀이

f(x) 를 x 이하의 a 원소들로 나누어지는 자연수의 수 라고 하자

답은 f(r) - f(l - 1) 이 되겠다

f(x) 는 포함배제의 원리로

+ {원소 하나로 나누어지는 경우의 수}  - {원소 두개로 모두 나누어지는 경우의 수} ... 

이므로 고려한 수 가 홀수면 + 짝수면 - 를 곱해준다

 

시간복잡도는

$O(2^N + Nlog(1e9))$ 정도가 되겠다 

( 원소 선택 경우의수 + euclidean algorithm )

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define ll long long
#define ld long double
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pair<int, int> > vpi;
typedef vector<vector<int>> vvi;
typedef pair<ll, ll> pll;
typedef tuple<ll, ll, ll> tlll;
typedef vector<ll> vl;
typedef vector<pair<ll, ll>> vpl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
int dr[4] = {0, 0, 1, -1};
int dc[4] = {1, -1, 0, 0};
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  #if !defined(ONLINE_JUDGE)
  freopen("../input.txt", "r", stdin);
  freopen("../output.txt", "w", stdout);
  #endif // ONLINE_JUDGE

  ll n, l, r;
  cin >> n >> l >> r;
  vl v(n);
  each(e, v) cin >> e;

  ll ansR = 0;
  ll ansL = 0;
  function<void(int, ll, int)> f = [&] (int cur, ll tmp, int cnt) {
    if (tmp > r) return;

    if (cur == n) {
      if (cnt > 0) {
        ll flag = (cnt % 2 ? 1 : -1);
        ansR += flag * (r / tmp);
        ansL += flag * ((l - 1) / tmp);
      }
      return;
    }

    f(cur + 1, tmp, cnt);
    f(cur + 1, tmp / gcd(tmp, v[cur]) * v[cur], cnt + 1);
  };

  f(0, 1, 0);
  cout << ansR - ansL;
}
728x90

'PS > BOJ' 카테고리의 다른 글

백준 25317번: functionx (C++)  (0) 2023.06.22
백준 25315번: N수매화검법 (C++)  (0) 2023.06.16
백준 16933번: 벽 부수고 이동하기 3 (C++)  (1) 2023.06.11
백준 2186번: 문자판  (0) 2023.06.10
백준 1082번: 방 번호  (0) 2023.06.10

문제링크

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

 

16933번: 벽 부수고 이동하기 3

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000), K(1 ≤ K ≤ 10)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.

www.acmicpc.net

풀이

  • 벽 부순 횟수 k, 행 r, 열 c 에 대해 BFS 돌린다
  • 낮/밤 판별은 이동횟수 % 2 로 할 수 있다
  • 이동 안할 때 큐 터지는 것에 주의
  • (낮/밤 , k, r, c 로 BFS 돌려도 풀 수 있긴 하다)

 

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define ll long long
#define ld long double
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pair<int, int> > vpi;
typedef vector<vector<int>> vvi;
typedef pair<ll, ll> pll;
typedef tuple<ll, ll, ll> tlll;
typedef vector<ll> vl;
typedef vector<pair<ll, ll>> vpl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
int dr[4] = {0, 0, 1, -1};
int dc[4] = {1, -1, 0, 0};
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  #if !defined(ONLINE_JUDGE)
  freopen("../input.txt", "r", stdin);
  freopen("../output.txt", "w", stdout);
  #endif // ONLINE_JUDGE

  int n, m, k;
  cin >> n >> m >> k;

  vs v(n);
  each(e, v) cin >> e;

  queue<tuple<int, int, int> > q;
  
  // k, r, c
  vector<vvi> vis(k + 1, vvi(n, vi(m)));

  q.push({0, 0, 0});
  vis[0][0][0] = true;
  int ans = 0;
  while (q.size()) {
    ++ans;
    int tmp = q.size();
    while (tmp--) {
      auto [fk, fr, fc] = q.front();
      int isDay = ans % 2;
      q.pop();
      if (fr == n - 1 && fc == m - 1) {
        cout << ans;
        return 0;
      }

      for (int dir = 0; dir < 4; ++dir) {
        int nr = fr + dr[dir];
        int nc = fc + dc[dir];
        int nk = fk;

        if (nr < 0 || nr >= n || nc < 0 || nc >= m) continue;
        if (vis[nk][nr][nc]) continue;
        if (v[nr][nc] == '1') {
          if (!isDay || fk == k) continue;
          nk++;
        }
        vis[nk][nr][nc] = true;
        q.push({nk, nr, nc});
      }

      // not move
      if (!isDay && vis[fk][fr][fc] != 2) {
        vis[fk][fr][fc] = 2;
        q.push({fk, fr, fc});
      }
    }
  }

  cout << -1;
}
728x90

'PS > BOJ' 카테고리의 다른 글

백준 25315번: N수매화검법 (C++)  (0) 2023.06.16
백준 1441번: 나누어 질까 (C++)  (0) 2023.06.13
백준 2186번: 문자판  (0) 2023.06.10
백준 1082번: 방 번호  (0) 2023.06.10
백준 22581번: IkaNumber  (0) 2022.07.12

문제링크

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

 

2186번: 문자판

첫째 줄에 N(1 ≤ N ≤ 100), M(1 ≤ M ≤ 100), K(1 ≤ K ≤ 5)가 주어진다. 다음 N개의 줄에는 M개의 알파벳 대문자가 주어지는데, 이는 N×M 크기의 문자판을 나타낸다. 다음 줄에는 1자 이상 80자 이하의

www.acmicpc.net

풀이

$dp[i][r][c]$ 를 만들고자 하는 문자열 target의 i 번째 문자 위치 부터 끝까지 만드려고 할 때 (r, c) 위치부터 출발했을 때 경우의 수 라고 정의한다.

답은 $sum(dp[0][r][c]) (r,c: v[r][c] = target[0])$ 가 되겠다

 

코드

#include <bits/stdc++.h>

using namespace std;

#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define ll long long
#define ld long double
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pair<int, int> > vpi;
typedef vector<vector<int>> vvi;
typedef pair<ll, ll> pll;
typedef tuple<ll, ll, ll> tlll;
typedef vector<ll> vl;
typedef vector<pair<ll, ll>> vpl;
typedef vector<vector<ll>> vvl;
typedef vector<string> vs;
int dr[4] = {0, 0, 1, -1};
int dc[4] = {1, -1, 0, 0};
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  #if !defined(ONLINE_JUDGE)
  freopen("../input.txt", "r", stdin);
  freopen("../output.txt", "w", stdout);
  #endif // ONLINE_JUDGE

  int n, m, k;
  cin >> n >> m >> k;

  vs v(n);
  each(e,v) cin >> e;

  string target;
  cin >> target;

  vector<vvi> dp(target.size(), vvi(n, vi(m, -1)));

  function<int(int, int, int)> f = [&](int cur, int r, int c) {
    if (cur == target.size() - 1) {
      return 1;
    }
    auto& ret = dp[cur][r][c];
    if (ret != -1) return ret;

    ret = 0;
    for (int kk = 1; kk <= k; ++kk) {
      for (int dir = 0; dir < 4; ++dir) {
        int rr = r + kk * dr[dir];
        int cc = c + kk * dc[dir];
        if (rr < 0 || rr >= n || cc < 0 || cc >= m) continue;
        if (v[rr][cc] != target[cur + 1]) continue;
        ret += f(cur + 1, rr, cc);
      }
    }
    return ret;
  };

  int ans = 0;

  FOR(i, 0, n) FOR(j, 0, m) if (v[i][j] == target.front()) ans += f(0, i, j);

  cout << ans;
}
728x90

'PS > BOJ' 카테고리의 다른 글

백준 1441번: 나누어 질까 (C++)  (0) 2023.06.13
백준 16933번: 벽 부수고 이동하기 3 (C++)  (1) 2023.06.11
백준 1082번: 방 번호  (0) 2023.06.10
백준 22581번: IkaNumber  (0) 2022.07.12
백준 1557번: 제곱 ㄴㄴ  (0) 2022.07.05

+ Recent posts