AtCoder Beginner Contest 335
結果
A - 202<s>3</s> : AC(2:15)
B - Tetrahedral Number : AC(6:32)
C - Loong Tracking : AC(22:48)
D - Loong and Takahashi : AC(60:34)
E - Non-Decreasing Colorful Path : 提出無し
A - 202<s>3</s>
英小文字と数字からなり「2023」で終わる文字列$${S}$$が与えられ、その末尾を「4」にして出力する問題
自分の回答
int main(){
string S;
cin >> S;
for(int i = 0; i < S.size(); i++){
if(i != S.size() - 1){
printf("%c", S[i]);
}
else{
printf("4\n");
}
}
}
そのまま
公式解説
省略
B - Tetrahedral Number
正整数$${N}$$が与えられ、非負整数の組$${(x,y,z)}$$であって$${x+y+z \leqq N}$$であるもの全てを辞書順で小さい順に出力する問題
自分の回答
int main(){
int N;
cin >> N;
int x = 0, y = 0, z = 0;
while(x < N){
printf("%d %d %d\n", x, y, z);
z++;
if(x + y + z > N){
z = 0;
y++;
}
if(x + y + z > N){
y = 0;
x++;
}
}
printf("%d %d %d\n",x,y,z);
}
小さい順に総当たり
公式解説
N=int(input())
for x in range(N+1):
for y in range(N+1):
for z in range(N+1):
if x+y+z<=N:
print(x,y,z)
Pythonによるもの
https://atcoder.jp/contests/abc335/editorial/9025より
そうかforでよかったか
C - Loong Tracking
座標平面上に$${N}$$パーツからなる龍が存在しパーツ$${1}$$を頭と言い、最初パーツ$${i}$$は$${(i,0)}$$に存在する
以下のクエリ$${Q}$$個を処理する問題
・1 C : 頭を方向$${C}$$へ$${1}$$移動させる。他のパーツは番号が一つ前のパーツがいた場所へ移動する
・2 p : パーツ$${p}$$のいる座標を出力する
自分の回答
int main(){
int N, Q;
cin >> N >> Q;
deque<pair<int, int>> P;
for(int i = 1; i <= N; i++){
P.push_back({i, 0});
}
for(int _ = 0; _ < Q; _++){
int q;
cin >> q;
if(q == 1){
char c;
cin >> c;
auto [i, j] = P.front();
if(c == 'R'){
P.push_front({i + 1, j});
}
else if(c == 'L'){
P.push_front({i - 1, j});
}
else if(c == 'U'){
P.push_front({i, j + 1});
}
else{
P.push_front({i, j - 1});
}
P.pop_back();
}
else{
int p;
cin >> p;
p--;
printf("%d %d\n", P[p].first, P[p].second);
}
}
}
dequeならpush_frontもアクセスも速いためそれで終わり
公式解説
https://atcoder.jp/contests/abc335/editorial/9026より
dequeを使わない方法
配列にpush_backしていって答える時は後ろからi番目がそれぞれのパーツのいる場所
なるほど
D - Loong and Takahashi
一辺が奇数$${N}$$マスである正方形のグリッドがある
グリッドの中央には高橋君が存在し、高橋君のいるマスを除いた全てのマスに上下左右の移動で一筆書きし全てのマスを通るにはどのように移動すればいいか求める問題
自分の回答
void move(int &i, int &j, queue<char> d){
if(d.front() == 'R'){
j++;
}
else if(d.front() == 'D'){
i++;
}
else if(d.front() == 'L'){
j--;
}
else{
i--;
}
}
int main(){
int N;
cin >> N;
vector<vector<int>> F(N + 2, vector<int>(N + 2, -1));
for(int i = 1; i <= N; i++){
for(int j = 1; j <= N; j++){
if(i == (N + 1) / 2 && j == (N + 1) / 2){
continue;
}
F[i][j] = 0;
}
}
queue<char> d;
d.push('R');
d.push('D');
d.push('L');
d.push('U');
int m = 1, i = 1, j = 0;
while(m <= N * N - 1){
int goi = i,goj = j;
move(goi, goj, d);
if(F[goi][goj] != 0){
d.push(d.front());
d.pop();
goi = i,goj = j;
move(goi, goj, d);
}
F[goi][goj] = m;
m++;
i = goi, j = goj;
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= N; j++){
if(i == (N + 1) / 2 && j == (N + 1) / 2){
printf("T ");
continue;
}
printf("%d ", F[i][j]);
}
printf("\n");
}
}
どんなサイズでも角から渦巻で行けるからそうして終わり
公式解説
省略
E - Non-Decreasing Colorful Path
$${N}$$頂点$${M}$$辺の連結な無向グラフがあり、各頂点には整数$${A_{v}}$$が書かれている
頂点$${1}$$から$${N}$$への単純なパスに対して、通った順に頂点の整数が広義単調増加であるならばその種類数を得点として得られ、そうでないなら$${0}$$となる
最大で何点得られるか求める問題
自分の回答
ダイクストラ法っぽい感じはするけど書ききれなかった
公式解説
struct UnionFind {
vector<int> data;
UnionFind(int size) : data(size, -1) { }
bool unionSet(int x, int y) {
x = root(x); y = root(y);
if (x != y) {
if (data[y] < data[x]) swap(x, y);
data[x] += data[y]; data[y] = x;
}
return x != y;
}
bool findSet(int x, int y) {
return root(x) == root(y);
}
int root(int x) {
return data[x] < 0 ? x : data[x] = root(data[x]);
}
int size(int x) {
return -data[root(x)];
}
};
int main(){
int n,m;
cin >> n >> m;
vector<int> a(n);
for(auto &nx : a){cin >> nx;}
UnionFind uf(n);
vector<vector<pair<int,int>>> vp(200005);
for(int i=0;i<m;i++){
int u,v;
cin >> u >> v;
u--;v--;
if(a[u]>a[v]){swap(u,v);}
if(a[u]==a[v]){uf.unionSet(u,v);}
else{vp[a[u]].push_back({u,v});}
}
vector<int> dp(200005,-1e9);
dp[uf.root(0)]=1;
for(auto &nx : vp){
for(auto [u,v] : nx){
u=uf.root(u);
v=uf.root(v);
if(dp[u]>0){
dp[v]=max(dp[v],dp[u]+1);
}
}
}
cout << max(0,dp[uf.root(n-1)]) << "\n";
return 0;
}
https://atcoder.jp/contests/abc335/editorial/9037より
点数が0となるルートを消して有向グラフとする
動的計画法をしたいが同じ値での移動が可能だとできないためUnion-Findでそれをまとめて動的計画法
なるほど
ダイクストラ法でもできるっぽい
この記事が気に入ったらサポートをしてみませんか?