NS Solutions Corporation Programming Contest 2023(AtCoder Beginner Contest 303) - AtCoder
B - Discord
隣接行列で 人 i が 人 j と前後で並んでいたか?を持っておいて、一度も並んでいない二人組の数を集計する
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' int main() { int n,m; cin >> n >> m; vector a(m, vector<int>(n)); REP(i,m) REP(j,n) { cin >> a[i][j]; a[i][j]--; } vector s(n, vector<bool>(n)); REP(i,m) REP(j,n) { int now = a[i][j]; int prev = a[i][max(0,j-1)]; int nx = a[i][min(n-1,j+1)]; s[now][prev] = s[now][nx] = true; } int ans = 0; REP(i,n) for(int j = i+1; j < n; j++) if (!s[i][j]) ans++; cout << ans << endl; return 0; }
C - Dash
そのままシュミレーションする。
今いる地点に回復アイテムがあるかの判定は set を使うと楽。 回復アイテムは複数回使うことはできないので、使ったら set から削除しておく。
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using P = pair<int,int>; map<char,P> mp { {'R', {1,0}}, {'L', {-1,0}}, {'U', {0,1}}, {'D', {0,-1}} }; int main() { int n,m,h,k; cin >> n >> m >> h >> k; string s; cin >> s; set<P> st; REP(i,m) { int x,y; cin >> x >> y; st.emplace(x,y); } int nx = 0, ny = 0; bool ok = true; REP(i,n) { auto [dx,dy] = mp[s[i]]; nx += dx, ny += dy; h--; if (h < 0) { ok = false; break; } if (st.count({nx,ny}) && (h < k)) { h = k; st.erase({nx,ny}); } } cout << (ok ? "Yes" : "No") << endl; return 0; }
D - Shift vs. CapsLock
以下のように DP を定義して解いた
dp[i][j] := i 文字目までみたとき、 CapsLock の状態が j( on/off ) のときの最短の時間
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using ll = long long; const ll LINF = 1e18; template<class T> void chmin(T& a, T b) { a = min(a,b); } int main() { ll x,y,z; cin >> x >> y >> z; string s; cin >> s; int n = s.size(); vector dp(n+1, vector<ll>(2,LINF)); dp[0][0] = 0; dp[0][1] = z; REP(i,n) { // CapsLock off if (s[i] == 'a') { chmin(dp[i+1][0], dp[i][0] + x); chmin(dp[i+1][1], dp[i][0] + z + y); } else { chmin(dp[i+1][0], dp[i][0] + y); chmin(dp[i+1][1], dp[i][0] + z + x); } // CapsLock on if (s[i] == 'a') { chmin(dp[i+1][1], dp[i][1] + y); chmin(dp[i+1][0], dp[i][1] + z + x); } else { chmin(dp[i+1][1], dp[i][1] + x); chmin(dp[i+1][0], dp[i][1] + z + y); } } ll ans = min(dp[n][0],dp[n][1]); cout << ans << endl; return 0; }
E - A Gift From the Stars
次数が 1 の頂点と隣接している頂点は必ず星の中心となる。その星の中心と隣接している頂点を調べ、次数が 2 以上の頂点は他の星と連結しているため、さらにそこを探索する。これを候補がなくなるまで繰り返す。
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' int main() { int n; cin >> n; vector g(n,vector<int>()); vector<int> deg(n); REP(i,n-1) { int u,v; cin >> u >> v; u--; v--; g[u].push_back(v); g[v].push_back(u); deg[u]++; deg[v]++; } // 頂点 i から 次数が 1 より大きい頂点を探す auto f = [&](int i) { if (i >= 0) for(auto v: g[i]) if (deg[v] > 1) return v; return -1; }; vector<int> ans; queue<int> q; REP(i,n) if (deg[i] == 1) q.push(i); while(q.size()) { int center = f(q.front()); q.pop(); if (center == -1) continue; deg[center] = 0; for(auto v: g[center]) { deg[v]--; if (deg[v] == 1) q.push(f(v)); } ans.push_back(g[center].size()); } sort(ans.begin(),ans.end()); for(int v: ans) cout << v << " "; return 0; }