パソコン甲子園に参加した話

夏休みが半分ほど終わってしまいました。こばです。
今日はパソコン甲子園に参加したのでその感想を記事にしようと思います。
結果から発表しますと、僕のチームが解いた問題数は5問(数字が小さい方から5問)でした。
アルゴリズムも何もない解き方でしたが、少し解説もしようと思います。
問題は過去問を参考にしてください。(もうすぐ公式サイトにアップされると思います。)
まず1番。これは入力された数字に32をかけるだけですね。
続いて2番。1つ目の数字に2つ目の数字を足してプラス、0、マイナスに三つで条件分岐すればいいです。
ここまでの問題は相方の〆鯖くんが解いてくれました。
2人ペアで参加できるので片方の人が簡単な問題を解いているうちに難しい問題のアルゴリズムを考えるという風に解いていくといいですね。今回これを実践してみたのですが効率よくスムーズにとけました。
3番は西暦から和暦、その逆を求める問題ですね。ここからはソースコードとともにご覧ください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
using namespace std;
 
int main(){
    int e,y,ans;
    cin >> e >> y;
    if(e == 0){
        if(y >= 1989){
            ans = y - 1989 + 1;
            cout << "H" << ans << endl;
            return 0;
        }
        else if(y >= 1926){
            ans = y - 1926 + 1;
            cout << "S" << ans << endl;
            return 0;
        }
        else if(y >= 1912){
            ans = y - 1912 + 1;
            cout << "T" << ans << endl;
            return 0;
        }
        else{
            ans = y - 1868 + 1;
            cout << "M" << ans << endl;
            return 0;
        }
         
    }
    else if(e == 1){
        cout << y + 1868 - 1 << endl;
    }
    else if(e == 2){
        cout << y + 1912 - 1 << endl;
    }
    else if(e == 3){
        cout << y + 1926 - 1 << endl;
    }
    else if(e == 4){
        cout << y + 1989 - 1 << endl;
    }
    return 0;
}

こんな感じですね。これはわかりやすいので見てわかると思います。
続いて4番。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
using namespace std;
 
int main(){
    int w,h,c,k,y,i;
    cin >> w >> h >> c;
    if(w < h){
        k = h;
    }
    else{
        k = w;
    }
    for(i = 1;i < k+1;i++){
        if(w % i == 0 && h % i == 0){
            y = i;
        }
    }
    cout << ((w / y) * (h / y)) * c << endl;
    return 0;
}

1つ目、2つ目の数字の最大公約数を求めて、整備する区画のブロックの数を出し、区画の整備コストを掛け合わせていますね。
最後に5番です。これは重複している面の数から消す面の数を求める問題です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<iostream>
using namespace std;
 
int main(){
    int n,hoge,i,j,hogehoge = 0;
    int p[3][1000] = {0};
    cin >> n;
    for(i = 0;i < n;i++){
        for(j = 0;j < 3;j++){
            cin >> p[j][i];
        }
    }
    for(i = 0;i < n;i++){
        if(p[1][i] < p[0][i] && p[1][i] < p[2][i]){
            hoge = p[1][i];
            p[1][i] = p[0][i];
            p[0][i] = hoge;
        }
        else if(p[2][i] < p[0][i]){
            hoge = p[2][i];
            p[2][i] = p[0][i];
            p[0][i] = hoge;
        }
        if(p[1][i] > p[2][i]){
            hoge = p[2][i];
            p[2][i] = p[1][i];
            p[1][i] = hoge;
        }
    }
    for(i = 0;i < n;i++){
        for(j = i;j < n-1;j++){
            if(p[1][i] == p[1][j+1] && p[2][i] == p[2][j+1] && p[0][i] == p[0][j+1] && p[0][i] != 0){
                hogehoge++;
                p[0][j+1] = 0;
                p[1][j+1] = 0;
                p[2][j+1] = 0;
            }
        }
    }
    cout << hogehoge << endl;
    return 0;
}

5番はソースが汚くて申し訳ないです….めちゃくちゃですね。
僕が使った求め方はまず全ての面の頂点の情報を小さい・・・・大きいといったように並べ替えます。並べ替えると同じ面が一目瞭然なので、面を検出します。検出したものは全て0に更新し、更新した後の全て0の面は同じ面であると認識しないような処理も加えると完成です。
6番…は解けるような気はしたのですが間に合いませんでした。(間に合っても合ってるかどうかわからないですが。)

今回のパソコン甲子園で5番を解いているときに一度エラーのようなものが起きました。
それはコンパイル中、入力を終えているにも関わらず入力待ちの状態で点滅し、しかも入力できないというエラーが起こりました。
エラーに対応できず5番は問題になっていた処理を大きく変えることで回答できましたが、6番でも同様のエラーが起こり時間切れになってしまいました。実はまだエラーの正体がつかめていないのできちんとどうしてエラーが起きたのかを理解し、来年に生かそうと思います。
最後まで読んで頂きありがとうございました。


コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください