Roman Numerals ---解题报告

 又是一道ACM题。这题很早前看过的,但是当时没怎么想。今天受人之托,认真做了下,发现也不怎么难。这题做的好高兴,时间,代码长度都比较靠前,虽然数据是随机的,时间上带有偶然性,不过确实很兴奋。最重要的是,一次AC,呵呵。

 

 

题目出处:

北大:http://acm.pku.edu.cn/JudgeOnline/problem?id=1213

吉大:http://acm.jlu.edu.cn/joj/showproblem.php?pid=1800&off=1800

 

题目描述:

给定一个式子(只含下面给定的字符),判断在罗马数字表达式里,是不是成立(成立,输出correct ,否则输出Incorrect) 。对于阿拉伯数字是不是成立 (如果只有一个,则是vaild;多个,则是ambiguous;不可能,则是impossible)。

罗马数字里:

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

阿拉伯数字里:

只要不同的字符对应的数字不同,而且没有前缀0就行了。

 

题目中,还列举了一些规则,这些都不用管的,只要知道,对于罗马的,如果连续二个字符中,第一个字符对应的数小于第二个字符对应的数,则第一个数为负数。其余的都是正数,直接加起来就行了。

 

输入:

一个字符串,

输出:

上面已经指出了。

 

 

思路:

1。判断罗马数字很简单,因为输入的格式都是正确的,直接根据上面规则就行了。

2。难点在于判断是不是阿拉伯的。我的做法是,先统计出现的不同字符。然后用回溯。假设每个数字对应0~9的情况。

如果超过两种,直接返回,这样算是一个剪枝。用一个visit[]标志,该数字是不是被其他字符用过的。回溯,给每个字符赋值。然后再判断式子成不成立 。

 

 

代码:

#include<iostream> #include<string> using namespace std; int n; string str; int help(char c) { if(c=='I') return 1; if(c=='V') return 5; if(c=='X') return 10; if(c=='L') return 50; if(c=='C') return 100; if(c=='D') return 500; return 1000; } int solve(int &i) { int s=0; for(;str[i]!='/0';i++) { if(str[i]>='A'&&str[i]<='Z') { if(i+1<n&&str[i+1]>='A'&&str[i+1]<='Z'&&help(str[i])<help(str[i+1])) { s=help(str[i+1])-help(str[i])+s; i++; } else s+=help(str[i]); } else break; } i++; return s; } bool Roman() { int a,b,c; int i; i=0; a=solve(i); b=solve(i); c=solve(i); if(a+b==c) return true; return false; } char ans[10]; int key[30]; int m; int visit[10]; int total; void just(int k) { if(total>1) return; int i,j; int a,b,c; if(k==m) { a=0; for(i=0;i<n;i++) { if(str[i]=='+') break; if(i==0&&key[str[i]-'A']==0&&str[i+1]!='+') return; a=a*10+key[str[i]-'A']; } i++; b=0; for(j=i;i<n;i++) { if(str[i]=='=') break; if(i==j&&key[str[i]-'A']==0&&str[i+1]!='=') return; b=b*10+key[str[i]-'A']; } i++; c=0; for(j=i;i<n;i++) { if(i==j&&key[str[i]-'A']==0&&i+1<n) return; c=c*10+key[str[i]-'A']; } if(a+b==c) total++; return ; } for(i=0;i<10;i++) { if(visit[i]==0) { key[ans[k]-'A']=i; visit[i]=1; just(k+1); if(total>1) return ; visit[i]=0; } } } int Arbit() { int i,j; m=0; for(i=0;i<n;i++) { if(str[i]>='A'&&str[i]<='Z') { for(j=0;j<m;j++) if(str[i]==ans[j]) break; if(j==m) ans[m++]=str[i]; } } for(i=0;i<10;i++) visit[i]=0; //找出了字符 total=0; just(0); return total; } int main() { while(cin>>str) { if(str=="#") break; n=str.size(); if(Roman()) cout<<"Correct "; else cout<<"Incorrect "; if(Arbit()==0) cout<<"impossible"; else if(Arbit()==1) cout<<"valid"; else cout<<"ambiguous"; cout<<endl; } return 0; }

你可能感兴趣的:(Roman Numerals ---解题报告)