0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[AtCoder]AtCoder Beginner Contest 129

Posted at

はじめに

  • AtCoder Beginner Contestの過去問の解法及び提出したソースコードをまとめています。
  • 基本的に自分が振り返ることを目的としておりますが、誤りや気になった点、その他質問等もお待ちしておりますので遠慮なくお願いします。

コンテストページ

A問題

3つのうちの小さい方から2つを足し合わせた値が解です。
3つの合計から3つのうちもっとも大きいものを引いてあげると実装がスッキリします。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int p,q,r;
    cin >> p >> q >> r;
    cout << p + q + r - max({p,q,r}) << endl;
    return 0;
}

B問題

区切り点を移動させて全探索します。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<int> w(n);
    for(int i = 0; i < n; i++) cin >> w[i];

    int ans = INT32_MAX;
    for(int i = 0; i < n; i++){
        int s1  = accumulate(w.begin(), w.begin() + i, 0);
        int s2  = accumulate(w.begin() + i, w.end(), 0);
        ans = min(ans, abs(s1-s2));
    }

    cout << ans << endl;
    return 0;
}

C問題

1つ前と2つ前の段への移動方法の合算がその段への移動方法パターン数です。
また0段目への行き方は1通り、壊れている段への移動方法は0通りと考えます。
段が壊れているかどうかの判定はunordered_setに予め壊れている段を入れておき確認できるようにしています。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    const int MOD = 1000000007;
    int n,m;
    cin >> n >> m;
    unordered_set<int> a;
    vector<int> dp(n+1, 0);
    dp[0] = 1;

    for(int i = 0; i < m; i++){
        int tmp;
        cin >> tmp;
        a.insert(tmp);
    }

    int ans = 0;
    for(int i = 1; i <= n; i++){
        if(a.count(i)) continue;
        if(a.count(i-1) == 0) dp[i] += dp[i-1];
        if(a.count(i-2) == 0) dp[i] += dp[i-2];
        dp[i] %= MOD;
    }
    
    cout << dp[n] << endl;
    return 0;
}

D問題

全てのマスの上下左右方向への空きマス数(そのマスを含む)を別々に計算します。
求め方は愚直にやるとO(HW(H+W))となり間に合いませんが、以下のようにすることでそれぞれO(HW)で求まります。

  • 上方向への空きマス数(u) = 上隣のマスの左方向への空きマス数 + 1
  • 下方向への空きマス数(d) = 下隣のマスの左方向への空きマス数 + 1
  • 左方向への空きマス数(l) = 左隣のマスの左方向への空きマス数 + 1
  • 右方向への空きマス数(r) = 右隣のマスの左方向への空きマス数 + 1

最後に全てのマスの全方向への空きマス数を求めますが、別々に計算した上下左右方向の空きマス数は自マスを重複して数えているため(u+d+l+r)を-3する必要があります。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int h,w;
    cin >> h >> w;
    vector<string> s(h);
    for(int i = 0; i < h; i++) cin >> s[i];
    vector<vector<int>> l(h, vector<int>(w));
    vector<vector<int>> r(h, vector<int>(w));
    vector<vector<int>> u(h, vector<int>(w));
    vector<vector<int>> d(h, vector<int>(w));

    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            if(s[i][j] == '#') l[i][j] = 0;
            else if(j==0) l[i][j] = 1;
            else l[i][j] = l[i][j-1] + 1;
        }
    }
    for(int i = 0; i < h; i++){
        for(int j = w-1; j >= 0; j--){
            if(s[i][j] == '#') r[i][j] = 0;
            else if(j==w-1) r[i][j] = 1;
            else r[i][j] = r[i][j+1] + 1;
        }
    }
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            if(s[i][j] == '#') u[i][j] = 0;
            else if(i==0) u[i][j] = 1;
            else u[i][j] = u[i-1][j] + 1;
        }
    }
    for(int i = h-1; i >= 0; i--){
        for(int j = 0; j < w; j++){
            if(s[i][j] == '#') d[i][j] = 0;
            else if(i==h-1) d[i][j] = 1;
            else d[i][j] = d[i+1][j] + 1;
        }
    }

    int ans = 0;
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            ans = max(ans, l[i][j] + r[i][j] + u[i][j] + d[i][j] - 3);
        }
    }
    
    cout << ans << endl;
    return 0;
}

E問題(未AC)

F問題(未AC)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?