AtCoder Beginner Contest 113(ABC113) 解説

ABC

本日2つ目のABCです。

A – Discount Fare

A - Discount Fare
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.

問題文の通り、X(A駅からB駅)+Y(B駅からC駅)/2(特別券)をすればOKです。

#include<bits/stdc++.h>

using namespace std;

int main(){
    int X,Y;
    cin>>X>>Y;
    cout<<X+Y/2<<endl;
}

B – Palace

B - Palace
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.

これも問題文の通り、N個に対してT−x×0.006 を計算し、Aとの差が最も小さいものを出力すればOKです。

#include<bits/stdc++.h>

using namespace std;

int main(){
    int N;
    int T,A;
    cin>>N>>T>>A;

    double mxv=DBL_MAX;
    int mx=-1;
    for(int i=0;i<N;i++){
        double H;
        cin>>H;
        double kion=T-H*0.006;
        double sa=abs(A-kion);
        if(sa<mxv){
            mx=i;
            mxv=sa;
        }
    }

    cout<<mx+1<<endl;
}

C – ID

C - ID
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.

発想自体は簡単で、PごとにYの昇順でまとめて、小さい順に番号を割り当てるだけです。
ただ実装がやや難しく、出力の形式も厄介です。

#include<bits/stdc++.h>

using namespace std;

int main(){
    int N,M;
    cin>>N>>M;

    map<int,int> m[N+1];

    for(int i=0;i<M;i++){
        int P,Y;
        cin>>P>>Y;
        m[P].emplace(Y,i);
    }

    string ans[M];

    for(int i=1;i<=N;i++){
        auto it=m[i].begin();
        int c=1;
        while(it!=m[i].end()){
            string tmp="";
            int n=c;
            for(int j=0;j<6;j++){
                tmp=(char)(n%10+'0')+tmp;
                n/=10;
            }
            n=i;
            for(int j=0;j<6;j++){
                tmp=(char)(n%10+'0')+tmp;
                n/=10;
            }
            ans[it->second]=tmp;
            it++;
            c++;
        }
    }

    for(int i=0;i<M;i++){
        cout<<ans[i]<<endl;
    }
}

結構ゴリゴリ書いてしまいました。
私は、int型から0埋めのstring型を生成していますが、printfの書式設定で%06dをすれば一発みたいです。(他の提出を覗いてみました)

以下、書きなおしです。

#include<bits/stdc++.h>

using namespace std;

int main(){
    int N,M;
    cin>>N>>M;
    int P[M],Y[M];
    map<int,int> m[N+1];

    for(int i=0;i<M;i++){
        cin>>P[i]>>Y[i];
        m[P[i]].emplace(Y[i],i);
    }

    int ans[M];

    for(int i=1;i<=N;i++){
        auto it=m[i].begin();
        int c=1;
        while(it!=m[i].end()){
            ans[it->second]=c++;
            it++;
        }
    }

    for(int i=0;i<M;i++){
        printf("%06d%06d\n",P[i],ans[i]);
    }
}

かなりスッキリしたかと思います。

D – Number of Amidakuji

D - Number of Amidakuji
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.

高さiの時にどの縦棒にいるかをdpで管理すれば解けそうです。ややこしさとして、横棒の引くパターンが少し面倒なことです。
入力例の絵にはありませんが、ある高さに2本横棒が引いてあるパターン(1と2,4と5みたいなの)もあるので、単純にはいかなさそうです。

今回、制約が弱いということもあり、bit全探索で「正しいあみだくじ」かは関係なく全パターンの横棒を列挙し、その中から「正しいあみだくじ」である横棒の引き方であるものに対し、dpの遷移をするようにしました。

#include<bits/stdc++.h>

using namespace std;

int main(){
    int H,W,K;
    long long mod=1000000007;
    cin>>H>>W>>K;

    long long dp[H+1][W+1];
    for(int i=0;i<H+1;i++){
        for(int j=0;j<W+1;j++){
            dp[i][j]=0;
        }
    }
    dp[0][1]=1;

    for(int i=1;i<=H;i++){
        for(int j=1;j<=W;j++){
            for(int k=0;k<(1<<(W-1));k++){
                bool f=false;
                int n=k;
                int mv=0;
                bool t=false;
                for(int l=0;l<W-1;l++){
                    if(n%2==1){
                        if(t) f=true;
                        else t=true;
                        int idx=W-l;
                        if(idx==j) mv=-1;
                        if(idx-1==j) mv=1;
                    }
                    else t=false;
                    n/=2;
                }
                if(f) continue;
                dp[i][j]+=dp[i-1][j+mv];
                dp[i][j]%=mod;
            }
        }
    }

    cout<<dp[H][K]<<endl;
}

“あみだくじ”と聞いて、縦に連結する問題かと思ったのですが違ってビックリしました。> <

コメント

タイトルとURLをコピーしました