歡迎加入我的 Discord 群組與我討論程式相關的問題!

Posted on 

 by 

 in 

ZeroJudge a013. 羅馬數字

評分:1.5 分,滿分為 5。

題目連結

題意

給兩個羅馬數字,要你用兩個羅馬數字輸出兩個絕對值。

羅馬數字的規則是:

I: 1
V: 5
X: 10
L: 50
C: 100
D: 500
M: 1000

從左往右把數字都加起來。如果有比較小的數字出現在比較大的數字之前則是要把他剪掉,例如: IV = 4, IX = 9。如果出現四個一樣的字母就要改用減法表示。

解題方法

這邊我把主要的功能都寫成 function,維持程式碼的簡潔。

羅馬數字轉十進位:

我先寫了一個把對應字母轉成數字的 function,接著再跑過一個迴圈,如果前面的數字比下一個大就把它減掉,反之就加上它,就可以把一串羅馬數字變成十進位了。

十進位轉羅馬數字:

我先直接把可能出現的排列都列出來: “M”, “CM”, “D”, “CD”, “C”, “XC”, “L”, “XL”, “X”, “IX”, “V”, “IV”, “I”。有些同學可能會擔心減法的部分會有很多種,但實際上就只有這些而已,大家可以仔細想想為甚麼。把他們都列好了之後,我們就可以貪心的從最大的開始拿,直到剩下的數字比現在的字母還小,就往下繼續拿。

#include <bits/stdc++.h>
using namespace std;
int f(char a){
    if(a == 'I') return 1;
    else if(a == 'V') return 5;
    else if(a == 'X') return 10;
    else if(a == 'L') return 50;
    else if(a == 'C') return 100;
    else if(a == 'D') return 500;
    else if(a == 'M') return 1000;
    return 0;
}
int romanToInt(string s) {
    vector <int> a;
    for(int i = 0;i < s.size();i++){
        a.push_back(f(s[i]));
    }
    int sum = 0;
    for(int i = 0;i < s.size();i++){
        if(i < s.size() - 1 && a[i] < a[i+1]) sum -= a[i];
        else sum += a[i];
    }
    return sum;
}
string intToRoman(int num) {
    int val[13] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    string ans[13] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
    int p = 0;
    string res = "";
    while(num) { // 直到被拿成 0 之前都繼續
        int cnt = num / val[p]; // 計算它最多可以拿幾個
        for(int i = 0;i < cnt;i++) {
            res += ans[p];
        }
        num -= val[p] * cnt;
        p++;
    }
    return res;
}
int main(){
	string a, b;
	while(cin >> a) {
		if(a == "#") break;
		cin >> b;
		int na = romanToInt(a), nb = romanToInt(b);
		if(na == nb) cout << "ZERO\n";
		else cout << intToRoman(abs(na - nb)) << '\n';
	}
}

另外,Leetcode 上面有兩題都是裸的羅馬數字的題目,那邊的測試資料會比較強一點。想確認自己程式是否是對的同學可以去看看! 羅馬轉十進位 十進位轉羅馬

圖片來源:https://www.cuemath.com/numbers/roman-numerals-conversion/

發表迴響

Blog at WordPress.com.

%d 位部落客按了讚: