hogecoder

tsutaj 競技プログラミングの記録

AOJ 0039: Roman Figure

AOJ修行なう。今日中に50ACしたい・・・

問題概要

原文 → ローマ数字 | Aizu Online Judge

ローマ数字を10進アラビア数字に直せ。

解説

私は文字列の後ろから見ていくことにしました。

今注目している文字の左隣が自分と同じ値 または 自分より大きい値を指すならば、そのまま足すことができます。しかし、左隣が自分より小さい値である場合は、その数を引かなければいけません。

例えば、XXIは後ろから見ていくと単調増加なので引く操作は必要ありませんが、XIVはVの左隣がIであるため、1引く必要があります。

ちなみに、このコードはSTLのmapを使えばもっと簡潔に書けますが、ぱっと思い浮かんだコードがこれだったのでご勘弁を。

#include <bits/stdc++.h>
using namespace std;
 
#define rep(i,a,n) for(int i=a; i<n; i++)
#define repr(i,a,n) for(int i=a; i>=n; i--)
 
int main() {
    string s;
    int a[51];
    while(cin >> s) {
        memset(a, -1, sizeof(a));
        // 文字が指し示す数字を配列に保存
        repr(i,s.length() - 1,0) {
            if(s[i] == 'I') a[i] = 1;
            else if(s[i] == 'V') a[i] = 5;
            else if(s[i] == 'X') a[i] = 10;
            else if(s[i] == 'L') a[i] = 50;
            else if(s[i] == 'C') a[i] = 100;
            else if(s[i] == 'D') a[i] = 500;
            else if(s[i] == 'M') a[i] = 1000;
        }
 
        int prev = -1, ret = 0;
        repr(i,s.length() - 1,0) {
            // そのまま足せる
            if(a[i] >= prev) {
                prev = a[i];
                ret += a[i];
            }
            // 左隣のほうが小さいので、引く
            else {
                ret -= a[i];
            }
        }
 
        cout << ret << endl;
    }
    return 0;
}

コンテスト形式じゃないと解答が遅くなるね。どうにかしたいね。