~をもとにしたACコード
という言い回しから察するに,そのコードはご自身で書かれたわけですよね?
何故この手のパズルをやってる人は一様にこのようなコードを書くのか?っていうその理由や必要性は知りませんが…
仮に,わざわざ呪文みたいなコードを書いてそれを自身で「イミフ」って言ってるのであれば,
少なくとも内容理解を目的とする状況下においては 前記の「理由や必要性」 は当てはまらないと思うので,そういう際にはもっと ご自身が読める/説明的/etc な形にコードを書いてみたら良いのではないでしょうか.
例えば…
N, Ai, i
といった,問題文に出てくる記号については,コードでも同じ記号を変数名にすればどうですか?(そしてこれらの変数を別の用途に使わない.例えば i
を別の意味合いのループに使わない)
- 以下のように感じに,変数の意味とか使い方を明記してみればどうですか?
- (ループ用の変なマクロは見た目に値域がわからないので,こういう場合にはやめた方が良いように思えますが,これは本人の慣れ次第かな?)
C++
1int main()
2{
3 //問題文と記号を合わせて { N, Ai } みたいな変数名を用いたら分かりやすいであろう.
4 int N, Ai;
5 std::cin >> N;
6
7 //呪文みたいな数式を書くんじゃなくて,意味がある値をその意味を示す名称の変数に保持してみるとか
8 const int nAmeba = 1 + 2*N; //アメーバの総数(まず最初の1匹がいて,記録1つにつき2匹増える)
9
10 //vectorの用途等も注釈なりで明記してみては?
11 // 各アメーバの親の番号を記録する用.
12 // ParentAmebaNo[ i ] には,番号i のアメーバの親の番号を記録する.
13 // アメーバの番号は 1-based な値なので,[0]は未使用.
14 std::vector<int> ParentAmebaNo( nAmeba+1 );
15
16 //(ループにわざわざ "rep1" みたいなマクロを使わない)
17 for( int i=1; i<=N; ++i ) //ここの変数名 i は問題文での記号に合わせてのこと
18 {
19 std::cin >> Ai;
20 ParentAmebaNo[ i*2 ] = Ai;
21 ParentAmebaNo[ i*2 + 1 ] = Ai;
22 }
23
24 //答えの記録用.
25 // Ans[ i ] には,番号i のアメーバが(最初のアメーバを「0世代目」として)何世代目なのかを記録する.
26 std::vector<int> Ans( nAmeba+1, 0 ); //ここでは Ans[1]=0 であることに意味があるのだから初期化値 0 を明記すると良いか
27 for( int AmebaNo=2; AmebaNo<=nAmeba; ++AmebaNo ) //ループ変数は意味が分かる名前にする
28 {
29 Ans[ AmebaNo ] = Ans[ ParentAmebaNo[AmebaNo] ] + 1;
30 }
31
32 //結果出力
33 for( int AmebaNo=1; AmebaNo<=nAmeba; ++AmebaNo )
34 {
35 std::cout << Ans[ AmebaNo ] << '\n';
36 }
37 return 0;
38}
親が何代目かがわかればそれに1足せば答えになると思うのですが、分裂番号が何代目かかを記録していくのではなく、A_iを分裂番号目の配列に記録していくことでなぜ答えにつながるのかがわかりません。
というコメントを受けての追記:
【あなたが言うようなアルゴリズムでも問題を解くことができますが,それは提示されたコードが使っているアルゴリズムとは異なる】というだけのことです.
分裂番号が何代目かを記録していく形の方法を実装するとしたら,例えば以下のようになるでしょうか.
C++
1int main()
2{
3 //問題文と記号を合わせて { N, Ai } みたいな変数名を用いたら分かりやすいであろう.
4 int N, Ai;
5 std::cin >> N;
6
7 //呪文みたいな数式を書くんじゃなくて,意味がある値をその意味を示す名称の変数に保持してみるとか
8 const int nAmeba = 1 + 2*N; //アメーバの総数(まず最初の1匹がいて,記録1つにつき2匹増える)
9
10 //i番目の記録での分裂によって発生したアメーバとは何世代目の存在なのか?を記録する用.
11 //※便宜上,最初の一匹目が「i=0 番目の分裂で発生した」と見なす.
12 std::vector<int> ANS_i( N+1, 0 ); //最初の一匹目用のデータとして,ANS_i[0] = 0 としておく
13
14 //各アメーバが何番目の分裂によって発生したのか?を記録する用.
15 // アメーバの番号は 1-based な値なので,[0]は未使用.
16 std::vector<int> iOfAmeba( nAmeba + 1, 0 ); //最初の一匹目用のデータとして,iOfAmeba[1] = 0 としておく
17
18 //N個の分裂記録を読込みつつ,内容を記録していく.
19 for( int i=1; i<=N; ++i ) //ここの変数名 i は問題文での記号に合わせてのこと
20 {
21 std::cin >> Ai;
22 ANS_i[ i ] = iOfAmeba[Ai] + 1;
23 iOfAmeba[ i*2 ] = i;
24 iOfAmeba[ i*2 + 1 ] = i;
25 }
26
27 //結果出力
28 for( int AmebaNo=1; AmebaNo<=nAmeba; ++AmebaNo )
29 {
30 std::cout << ANS_i[ iOfAmeba[AmebaNo] ] << '\n';
31 }
32 return 0;
33}