日期:2025年6月24日
ZeroJudge 題目連結:a013. 羅馬數字
解題想法
這題最麻煩的地方在於 900、400、90、40、9、4 的轉換,分別換成 CM、CD、XC、XL、IX、IV。程式碼寫起來很長,我想不到更精簡的寫法。
Python 程式碼
使用時間約為 17 ms,記憶體約為 3.4 MB,通過測試。
import sys
# 羅馬數字字串 s 換成整數
def rton(s):
# 字母換成對應的整數
cton = {'M': 1000, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}
n = n1 = cton[s[0]] # 第1位數
for c in s[1:]: # 依序讀取 s[1] ~ s[-1]
n2 = cton[c] # 對應的整數 n2
if n2 > n1: # 如果 n2 較大,n 加上 n2,減掉 2 倍 n1
n = n - 2*n1 + n2
else: # 反之,直接加上 n2
n = n + n2
n1 = n2 # 更新 n1
return n # 回傳 n
# 整數換成羅馬數字
def ntor(n):
s = "" # 儲存結果用的空字串
# 處理 1000 的倍數
M = n//1000; s += "M"*M; n %= 1000
# 處理 500 的倍數
D = n//500; s += "D"*D; n %= 500
# 處理 100 的倍數
C = n//100; n %= 100
if C == 4 and D == 1: # 900
s = s[:-1] # 刪除最後一位
s += "CM" # 加上 "CM"
elif C == 4 and D == 0: # 400
s += "CD" # 加上 "CM"
else: s += "C"*C # 其它狀況,加上 C 個 "C"
# 處理 50 的倍數
L = n//50; n %= 50
if L == 1: s += "L" # 如果 L 等於 1,加上 "L"
# 處理 10 的倍數
X = n//10; n %= 10
if X == 4 and L == 1: # 90
s = s[:-1] # 刪除最後一位
s += "XC" # 加上 "XC"
elif X == 4 and L == 0: # 40
s += "XL" # 加上 "XL"
else: s += "X"*X # 其它狀況,加上 X 個 "X"
# 處理 5 的倍數
V = n//5; n %= 5
if V == 1: s += "V" # 如果 V 等於 1,加上 "V"
# 處理 1
I = n
if I == 4 and V == 1: # 9
s = s[:-1] # 刪除最後一位
s += "IX" # 加上 "IX"
elif I == 4 and V == 0: # 4
s += "IV" # 加上 "IV"
else: s += "I"*I # 其它狀況,加上 I 個 "I"
# 回傳結果
return s
for line in sys.stdin:
if line.rstrip() == "#": break
a, b = line.split() # 羅馬數字 a, b
na, nb = rton(a), rton(b) # 轉成整數 na, nb
diff = abs(na - nb) # 差值
print("ZERO" if diff == 0 else ntor(diff))
C++ 程式碼
使用時間約為 2 ms,記憶體約為 324 kB,通過測試。
#include <iostream>
#include <string>
#include <map>
using namespace std;
/* 羅馬數字字串 s 換成整數 */
int rton(string s) {
// 字母換成對應的整數
map<char, int> cton = {{'M', 1000}, {'D', 500}, {'C', 100}, {'L', 50},
{'X', 10}, {'V', 5}, {'I', 1}};
int n = cton[s[0]]; // 第1位數
int n1 = n;
for(char c : s.substr(1)) { // 依序讀取 s[1] ~ s[-1]
int n2 = cton[c]; // 對應的整數 n2
if (n2 > n1) { // 如果 n2 較大,n 加上 n2,減掉 2 倍 n1
n = n - 2*n1 + n2;
} else { // 反之,直接加上 n2
n = n + n2;
}
n1 = n2; // 更新 n1
}
return n; // 回傳 n
}
/* 整數換成羅馬數字 */
string ntor(int n) {
string s = ""; // 儲存結果用的空字串
// 處理 1000 的倍數
int M = n/1000;
n %= 1000;
string t (M, 'M'); // 要補上 M 個字母 M
s += t;
// 處理 500 的倍數
int D = n/500;
n %= 500;
string td (D, 'D'); // 要補上 D 個字母 D
s += td;
// 處理 100 的倍數
int C = n/100;
n %= 100;
if (C == 4 && D == 1) { // 900
s.pop_back(); // 刪除最後一位
s += "CM"; // 加上 "CM"
} else if (C == 4 && D == 0) { // 400
s += "CD"; // 加上 "CM"
} else { // 其它狀況,加上 C 個 "C"
string tc (C, 'C');
s += tc;
}
// 處理 50 的倍數
int L = n/50;
n %= 50;
if (L == 1) { // 如果 L 等於 1,加上 "L"
string tL (L, 'L');
s += tL;
}
// 處理 10 的倍數
int X = n/10;
n %= 10;
if (X == 4 && L == 1) { // 90
s.pop_back(); // 刪除最後一位
s += "XC"; // 加上 "XC"
} else if (X == 4 && L == 0) { // 40
s += "XL"; // 加上 "XL"
} else { // 其它狀況,加上 X 個 "X"
string tx (X, 'X');
s += tx;
}
// 處理 5 的倍數
int V = n/5;
n %= 5;
if (V == 1) s += "V"; // 如果 V 等於 1,加上 "V"
// 處理 1
int I = n;
if (I == 4 && V == 1) { // 9
s.pop_back(); // 刪除最後一位
s += "IX"; // 加上 "IX"
} else if (I == 4 and V == 0) { // 4
s += "IV"; // 加上 "IV"
} else { // 其它狀況,加上 I 個 "I"
string tv (I, 'I');
s += tv;
}
// 回傳結果
return s;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0);
string a, b;
while(cin >> a) {
if (a == "#") break;
cin >> b; // 羅馬數字 a, b
int na = rton(a), nb = rton(b); // 轉成整數 na, nb
int diff = abs(na - nb); // 差值
cout << (diff == 0 ? "ZERO" : ntor(diff)) << "\n";
}
return 0;
}
沒有留言:
張貼留言