• 12.整数转罗马数字


    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

    字符 数值
    I 1
    V 5
    X 10
    L 50
    C 100
    D 500
    M 1000
    例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

    通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

    I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
    X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
    C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
    给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

    这道题简单的地方在于整数是在一定范围内的。
    

    罗列法

    这是最傻的一种方法。将1,2,3...9; 10,20,30...90; 100,200,300...900; 1000,2000,3000这些数所对应的罗马数字全部罗列出来。然后依次遍历整数的每一位。

        string intToRoman(int num) {
            string result;
            if(num/1000!=0)
               switch(num/1000){
                   case 1:{result+="M";break;}
                   case 2:{result+="MM";break;}
                   case 3:{result+="MMM";break;}
               }
            if((num%1000)/100!=0)
                switch((num%1000)/100){
                    case 1:{result+="C";break;}
                    case 2:{result+="CC";break;}
                    case 3:{result+="CCC";break;}
                    case 4:{result+="CD";break;}
                    case 5:{result+="D";break;}
                    case 6:{result+="DC";break;}
                    case 7:{result+="DCC";break;}
                    case 8:{result+="DCCC";break;}
                    case 9:{result+="CM";break;}
                }
            if((num%100)/10!=0)
                 switch((num%100)/10){
                    case 1:{result+="X";break;}
                    case 2:{result+="XX";break;}
                    case 3:{result+="XXX";break;}
                    case 4:{result+="XL";break;}
                    case 5:{result+="L";break;}
                    case 6:{result+="LX";break;}
                    case 7:{result+="LXX";break;}
                    case 8:{result+="LXXX";break;}
                    case 9:{result+="XC";break;}
                }
            if(num%10!=0)
                switch(num%10){
                    case 1:{result+="I";break;}
                    case 2:{result+="II";break;}
                    case 3:{result+="III";break;}
                    case 4:{result+="IV";break;}
                    case 5:{result+="V";break;}
                    case 6:{result+="VI";break;}
                    case 7:{result+="VII";break;}
                    case 8:{result+="VIII";break;}
                    case 9:{result+="IX";break;}
                }  
            return result;
        }
    

    这种算法也可以换种写法:

        string intToRoman(int num) {
            string res;
            vector<string> v1={"","M","MM","MMM"};
            vector<string> v2={"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};
            vector<string> v3={"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"};
            vector<string> v4={"","I","II","III","IV","V","VI","VII","VIII","IX"};
            return v1[num/1000]+v2[(num%1000)/100]+v3[(num%100)/10]+v4[num%10];
        }
    

    贪心算法

    每次通过查表找出当前最大的数,减去以后继续查表。那么表中应该包含哪些数字或是罗马数字呢?以1-9为例,9需要加入表中,6-8不用,因为6-8可以先加V,之后再加若干I即可。1,4,5需要加入表,而2-3不用,因为2-3其实就是加上若干I。

        string intToRoman(int num) {
            string res;
            vector<int> val={1000,900,500,400,100,90,50,40,10,9,5,4,1};
            vector<string> str={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
            for(int i=0;i<val.size();++i){
                while(num>=val[i]){
                    num-=val[i];
                    res+=str[i];
                }
            }
            return res;
        }
    
  • 相关阅读:
    树链剖分 (模板) 洛谷3384
    ST表 (模板) 洛谷3865
    IOI 2005 River (洛谷 3354)
    IOI 2005 River (洛谷 3354)
    poj1094 Sorting It All Out
    poj1094 Sorting It All Out
    spfa(模板)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    洛谷1850(NOIp2016) 换教室——期望dp
  • 原文地址:https://www.cnblogs.com/Frank-Hong/p/13384920.html
Copyright © 2020-2023  润新知