• [Swust OJ 666]--初来乍到(题号都这么溜~~,递归,找规律)


    题目链接:http://acm.swust.edu.cn/problem/0666/

    Time limit(ms): 1000      Memory limit(kb): 65535
     
    Description
    小李去埃及旅游,但是初来乍到的他不认识罗马数,所以请你将阿拉伯数n ( 0 < n <= 1000)改写为罗马数.
     
    Input
    N行数据,每行一个满足0 < n <= 1000的数; 
    结束以EOF判断
     
    Output
    每行一个,见输出示例
     
    Sample Input
    1
    10
    35
    99
    400

    Sample Output
    1=I
    10=X
    35=XXXV
    99=XCIX
    400=CD

     
    基本数字: 
    I:一 V:五 X:十 L:五十 C:一百 D:五百 M:一千 
    记数方法 
      (1)相同的数字连写,所表示的数等于这些数字相加得到的数,如: Ⅲ = 3; 
      (2)小的数字在大的数字的右边,所表示的数等于这些数字相加得到的数, 如:Ⅷ = 8;Ⅻ = 12; 
      (3)小的数字,(限于Ⅰ、X 和 C)在大的数字的左边,所表示的数等于大数减小数得到的数,如:Ⅳ = 4;Ⅸ = 9; 
      (4)在一个数的上面画一条横线,表示这个数增值 1 000 倍,如:Ⅻ = 12 000 。 
    编辑本段 
    组数规则 
      (1)基本数字Ⅰ、X 、C 中的任何一个,自身连用构成数目,或者放在大数的右边连用构成数目,都不能超过三个;放在大数的左边只能用一个。 
      (2)不能把基本数字 V 、L 、D 中的任何一个作为小数放在大数的左边采用相减的方法构成数目;放在大数的右边采用相加的方式构成数目,只能使用一个。 
      (3)V 和 X 左边的小数字只能用Ⅰ。 
      (4)L 和 C 左边的小数字只能用×。 
      (5)D 和 M 左 边的小数字只能用 C 。
    Hint
     
     
    解题思路:这里讲两种方法,像这类题纯粹找规律,做这道题时,我分析了多个数的组成方式。例如1=I,2=II,3=III,4=IV,5=V,6=VI,7=VII,8=VIII,9=IX,10=X······
         其实后面的数都和1~9的形式一样,只需要分析每位的数值就行;下面是一些关键数值39=XXXIX,40=XL,49=XLIX,50=L,89=LXXXIX,90=XC······
         因此想399,499,899这几种数就是分界点;最后只需从首位递归下去就可以了~~~
     
    代码如下:
     1 #include<iostream>
     2 using namespace std;
     3 char key[20], X[] = " IXCMVLD";//数的五倍用i+4表示
     4 int cnt;
     5 void Rserve(int x){
     6     int i, cur = 0, k = 0, lp = 1;
     7     while (x > cur){
     8         cur = 10 * cur + 9;
     9         k++;
    10     }
    11     for (i = 1; i < k; i++, lp *= 10);
    12     if (x <= 4 * lp - 1){
    13         for (i = 0; i < x / lp; i++)
    14             key[cnt++] = X[k];
    15     }
    16     else if (x <= 5 * lp - 1){
    17         key[cnt++] = X[k];
    18         key[cnt++] = X[k + 4];
    19     }
    20     else if (x <= 9 * lp - 1){
    21         key[cnt++] = X[k + 4];
    22         for (i = 0; i < x / lp - 5; i++)
    23             key[cnt++] = X[k];
    24     }
    25     else{
    26         key[cnt++] = X[k];
    27         key[cnt++] = X[k + 1];
    28     }
    29     if (x%lp) Rserve(x%lp);
    30 }
    31 int main(){
    32     int i, x;
    33     while (cin >> x){
    34         cnt = 0;
    35         Rserve(x);
    36         cout << x << '=';
    37         for (i = 0; i < cnt; i++)
    38             cout << key[i];
    39         cout << endl;
    40     }
    41     return 0;
    42 }
    View Code

    当然了这道题这么溜,直接分析数字的组成方式1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1,与这些数字相关联会发生比如3和4,8和9,之间数字构成有一个本质的变化,具体的看题目的规则吧,然后每一个数字对应一个罗马数字组合递归找就是了具体见下表

    1000 900 500 400 100 90 50 40 10 9 5 4 1
    M CM D CD C XC L XL X IX V IV I

    很溜的代码如下:

     1 #include <iostream>
     2 #include <string>
     3 using namespace std;
     4 int x[] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
     5 string L[] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
     6 string exchange(int n){
     7     string s;
     8     int i = 0;
     9     while (n){
    10         if (n >= x[i]){
    11             n -= x[i];
    12             s += L[i];
    13         }
    14         else
    15             i++;
    16     }
    17     return s;
    18 }
    19 int main(){
    20     int n;
    21     while (cin >> n){
    22         cout << n << '=';
    23         cout << exchange(n) << endl;
    24     }
    25     return 0;
    26 }
    View Code

    这个代码ce,不过拿来改造用来玩还是不错的,至少答案全正确

     1 #include <stdio.h>
     2 void main(){
     3     static char *a[][10] = { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"
     4         "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XCC", "", "C", "CC", "CCC",
     5         "CD", "D", "DC", "DCC", "DCCC", "CM" };
     6     int n, t, i, m;
     7     printf("Please enter number:");
     8     scanf("%d", &n);
     9     printf("%d=", n);
    10     for (m = 0, i = 1000; m < 3; m++, i /= 10){
    11         t = (n%i) / (i / 10);
    12         printf("%s", a[2 - m][t]);
    13     }
    14     printf("
    ");
    15 }
    View Code
  • 相关阅读:
    开源项目之小玩具---各种机器人开源硬件
    目标检测之显著区域检测---国外的一个图像显著区域检测代码及其效果图 saliency region detection
    目标检测之指尖检测---指尖检测的新方法几种
    模式匹配之sift--- sift图像特征提取与匹配算法代码
    vi 之行号操作---显示行号、跳到指定行
    模式匹配之图像融合---小波变换的融合
    目标检测之harr---角点检测harr 的opencv实现
    java写 excel
    矩阵连乘最小权值
    leetcode Word Break I II 算法分析
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4582012.html
Copyright © 2020-2023  润新知