読者です 読者をやめる 読者になる 読者になる

AtCoder Beginner Contest #001 復習

AtCoder 復習

はい。
http://abc001.contest.atcoder.jp

A - 積雪深差

Python2

n=input()
print n-input()

C++11

#include<bits/stdc++.h>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;


int main(){
    int mod=1000000007;
    int h1,h2;
    scanf("%d",&h1);
    scanf("%d",&h2);
    printf("%d\n",h1-h2);
    return 0;
}

他の人の回答見るまで気づかなかったけどPythonなら1行で出来ることだった。。。 print input()-input()
整数で引き算すれば特に何もないと思う。

B - 視程の通報

Python2

n=int(raw_input())
if n<100:
    print '00'
elif n<=5000:
    if n>=1000:
        print n*10/1000
    else:
        print '0'+str(n)[0]
elif n<=30000:
    print n*10/10000+50
elif n<=70000:
    print (n*10/10000-30)/5+80
else:
    print 89

C++11

#include<bits/stdc++.h>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;


int main(){
    int mod=1000000007;
    int m;
    scanf("%d",&m);
    if (m<100) {
        printf("00\n");
    } else if (m<=5000) {
        printf("%02d\n",m/100);
    } else if (m>=6000 && m<=30000) {
        printf("%d\n",m/1000+50);
    } else if (m>=35000 && m<=70000) {
        printf("%d\n",(m/1000-30)/5+80);
    } else {
        printf("%d\n",89);
    }
    return 0;
}

0.1kmは100m未満のことです。5km以下は5000m以下のことです。入力がメートルで与えられるので判定も全てメートルで処理したほうが良いです。

C - 風力観測

Python2

n,k=map(int,raw_input().split())
ans=chk=0
d=['N','NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW']
n=(n*10)+1125
if n>=36000:
    n-=36000
deg=d[n/2250]
chk=k*10/6
c=0
if chk>=3265: c=12
elif chk>=2845: c=11
elif chk>=2445: c=10
elif chk>=2075: c=9
elif chk>=1715: c=8
elif chk>=1385: c=7
elif chk>=1075: c=6
elif chk>=795: c=5
elif chk>=545: c=4
elif chk>=335: c=3
elif chk>=155: c=2
elif chk>=25: c=1
if c==0: deg='C'
print deg,c

C++11

#include<bits/stdc++.h>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;


int main(){
    int mod=1000000007;
    int Deg,Dis;
    scanf("%d %d",&Deg,&Dis);
    char dir[][4] = {"N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW","C"};
    Deg=Deg*10+1125;
    if (Deg>=36000) Deg-=36000;
    
    if (Dis<15) Deg=16;
    else Deg=Deg/2250;
    
    int w;
    if (Dis<15) w=0;
    else if (Dis<93) w=1;
    else if (Dis<201) w=2;
    else if (Dis<327) w=3;
    else if (Dis<477) w=4;
    else if (Dis<645) w=5;
    else if (Dis<831) w=6;
    else if (Dis<1029) w=7;
    else if (Dis<1245) w=8;
    else if (Dis<1467) w=9;
    else if (Dis<1707) w=10;
    else if (Dis<1959) w=11;
    else w=12;

    printf("%s %d\n",dir[Deg],w);

    return 0;
}

これも実数は信用しなかったので整数を使うようにした。方位は22.5度ずつズレるが、判定の度数は小数第2位まで見るのでそれに合わせて * 10して0-36000の範囲になるようにした。風力の計算は小数第2位が四捨五入されるのに合わせてifの判定の値を区切る必要がある。

D - 感雨時刻の整理

Python2

n=int(raw_input())

def age(p):
    p+=100
    p-=p%100
    return p

def tasu(q):
    return q-(q%5)+5

def hiku(r):
    return r-(r%5)

def form(s):
    s=str(s)
    return '0'*(4-len(s))+s
l=[]
for i in range(n):
    a,b=map(int,raw_input().split('-'))
    a=hiku(a)
    if b%100>55:
        b=age(b)
    elif b%100<55 and b%5!=0:
        b=tasu(b)
    l.append([a,b])
l.sort()
ans=[]
for i in l:
    if len(ans)==0:
        ans.append(i)
    else:
        if ans[-1][1]<i[0]:
            ans.append(i)
        else:
            ans[-1][1]=max(ans[-1][1],i[1])
for i in ans:
    print form(i[0])+'-'+form(i[1])

C++11

#include<bits/stdc++.h>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
 
 
int main(){
// #109801 写経
    int N;
    bool used[1500] = {0}; //bool配列を24時間 x 60分より大きく, 初期値は全て0で用意
 
    scanf("%d",&N);
    for (int i=0;i<N;i++) {
       int s,e; //降り始め時間をstart 降り終わり時間をend
       
       //時間は60をかけて分のみにして処理
       //降り始めと降り終わりの%5の丸めが異なる
       scanf("%d-%d",&s,&e);
       int ss=(s/100)*60 + (s%100);
       ss-=(ss%5);
       int ee=(e/100)*60 + (e%100);
       ee+=(5-(ee%5))%5;
 
       //雨降りの時間の範囲をtrueにする
       for (int j=ss;j<=ee;j++) {
           used[j]=true;
       }
    }
 
    for (int i=0;i<=24*60;i++) {
        //00時00分からか、それ以降の時間でiがtrueで、i-1がfalseの時間を降り始めとする
        if ((i==0 && used[i]) || (used[i] && !used[i-1])) {
            int h=i/60, m=i%60;
            printf("%02d%02d-",h,m);
        }
        if ((i==24*60 && used[i]) || (used[i] && !used[i+1])) {
            int h=i/60, m=i%60;
            printf("%02d%02d\n",h,m);
        }
    }
    return 0;
}

下記はPythonで書いたときの方針です。
時刻は受け取ったらすぐに丸めてしまう。例えば1130-1133と1136-1145は丸める前にマージしようとしても別々の時間帯の雨になるが1133は1135になり、1136も1135になるので1130-1145という1つのものになったりする場合があるので先に丸めてしまう。
丸めてからソートして早い時間のものから見ていく。おそらくは最初の時間から追加、マージしていくのに3パターンだけだと思う。
前提条件:ソートしているので新しい要素の方が降り始め時間が早いことはない。
1.時間が一部か全部重なる -> 降り始めは先にある要素の時間のまま、降り終わりは先にあるものと追加のものを比較して遅い方の時間にする。
2.時間が連続する -> 先にある要素の降り終わりと追加の要素の降り始めが同じ時刻の場合は先にある要素の降り始め-追加の要素の降り終わりで1つの要素にする。
3.離れた時間帯 -> 新しい要素を追加するだけ。ソートしているので後から早い降り始めのものが出てくることはないので追加すれば大丈夫。

C++11の方は配列の使い方とかがイメージがつかなかったので写経しました。解き方の方針?は推定でコード内にコメントで補足しました。