uva 185 Roman Numerals (深搜+字符串处理)

737 篇文章 0 订阅
223 篇文章 1 订阅


  Roman Numerals 

The original system of writing numbers used by the early Romans was simple but cumbersome. Various letters were used to represent important numbers, and these were then strung together to represent other numbers with the values decreasing monotonically from left to right. The letters they used and the numbers that were represented are given in the following table.

I1 V5
X10 L50
C100 D500
M1000   

Thus 1993 was written as MDCCCCLXXXXIII. This system was then superseded by a partially place-oriented system, whereby if the above rule of decreasing values was broken, it meant that the immediately preceding (lower) value was deemed to be `negative' and was subtracted from the higher (out of place) value. In this system 1993 was usually written as MCMXCIII. There is still some controversy as to which letters could precede which other letters, but for the purposes of this problem we will assume the following restrictions:

1.
A letter from the left column can never appear more than three times in a row, and there can never be more than one other occurrence of that letter.

2.
A letter from the right column can never appear more than once.

3.
Once a letter has been used in a `negative' position, all subsequent characters (apart from the one immediately following) may not be greater than that character.

Thus we could write MXMIII for 1993 or CCXCIV for 294, however we could not write ILV for 54, nor could we write LIL for 99. Note that 299 could be written as CCXCIX or CCIC


Given a Roman sum, we can either interpret it as such or as an encoding of an Arabic sum. Thus V+V=X could be interpreted as an ambiguous encoding of an Arabic sum with V $\in$ {1, 2, 3, 4} and X = 2 * V. Similarly, X+X=XX could be interpreted as a correct Roman sum but an impossible Arabic encoding (apart from the trivial encoding X = 0) and XX+XX=MXC as an incorrect Roman sum, but a valid encoding with M = 1, X = 9, and C = 8.


Write a program that will read in sums in Roman numerals and determine whether or not they are correct as Roman sums and also whether they are impossible, ambiguous or valid as Arabic encodings. Assume that zero will never appear on its own or as a leading digit, and that no two Roman numerals map onto the same Arabic digit.

Input 

Input will consist of a series of lines, each line consisting of an apparent Roman sum, i.e. a valid Roman number, a plus sign ( + ), another valid Roman number, an equal sign ( = ) and another valid Roman number. No Roman number will contain more than 9 letters. The file will be terminated by a line consisting of a single  # .

Output 

Output will consist of a series of lines, one for each line of the input, and each containing two words. The first word will be one of ( Correct, Incorrect ) depending on whether the Roman sum is or is not correct. The second word will be separated from the first by exactly one space and will be one of the set (impossible, ambiguous, valid) depending on the Arabic sum.

Sample input 

V+V=X
X+X=XX
XX+XX=MXC
#

Sample output 

Correct ambiguous
Correct impossible
Incorrect valid
题目大意:两个子问题,1是罗马数值是等式是否成立;2是是否存在阿拉伯数字是的等式成立(毫无疑问地相同的字母代表相同的数字,不同的字母只能代表不同的数字,字母位于首位的时候不能为0.
解题思路:枚举出所有字母的可能,然后计算等式是否是否成立,这种做法只要减掉刚才上面讲到的那些就可以过了。要注意的是,罗马数值的计算,当前面一个字母所表示的数值小于当前字母所表示的数值的时候,前面一个数值要相应的减掉。
#include <stdio.h>
#include <string.h>
#define N 1005

struct number{
    int val;
    char ch;
}tem[N];

int n, ok, cnt[3];
char S[3][N];

int change(char c){
    switch(c){
	case 'I':
	    return 1;
	case 'V':
	    return 5;
	case 'X':
	    return 10;
	case 'L':
	    return 50;
	case 'C':
	    return 100;
	case 'D':
	    return 500;
	case 'M':
	    return 1000;
	default:
	    return 0;
    }
}

bool judge(char str[]){
    int num[3] ={0}, len = strlen(str), t = 0, bo = 0;
    memset(cnt, 0, sizeof(cnt));
    memset(S, 0, sizeof(S));

    for (int i = 0; i <len; i++){
	if (str[i] != '+' && str[i] != '='){
	    num[bo] += change(str[i]);
	    if (t < change(str[i]))
		num[bo] -= 2 * t;
	    S[bo][cnt[bo]++] = str[i];
	    t = change(str[i]);
	}
	else{
	    t = 0;
	    bo++;
	}
    }

    return num[0] + num[1] == num[2]?true:false;
}

bool thesome(char c){
    for (int i = 0; i < n; i++)
	if (tem[i].ch == c)
	    return true;
    return false;
}

void handle(){
    for (int i = 0; i < 3; i++){
	for (int j = 0; j < cnt[i]; j++){
	    if (thesome(S[i][j]))	continue;
	    tem[n++].ch = S[i][j];
	}
    }
}

bool rep(int cur){
    for (int i = 0; i < cur; i++)
	if (tem[cur].val == tem[i].val)
	    return true;
    return false;
}

int find(char c){
    for (int i = 0; i < n; i++)
	if (tem[i].ch == c)
	    return tem[i].val;
    return 0;
}

int build(int cur){
    int sum = 0;
    for (int i = 0; i < cnt[cur]; i++)
       sum = sum * 10 + find(S[cur][i]);	
    return sum;
}

void dfs(int cur){

    if (cur == n){
	int num[3];
	for (int i = 0; i < 3; i++)
	    num[i] = build(i);
	if (num[0] + num[1] == num[2])
	    ok++;
    }
    else{
	int k = 0;
	for (int i = 0; i < 3; i++)
	    if (tem[cur].ch == S[i][0])
		k = 1;

	for (tem[cur].val = k; tem[cur].val <= 9; tem[cur].val++){
	    if (rep(cur))    continue;
	    dfs(cur + 1);
	}
    }
}

int main(){
    char str[N];
    while (scanf("%s", str)){
	if (strcmp(str, "#") == 0)  break;

	if (judge(str))
	    printf("Correct ");
	else
	    printf("Incorrect ");

	memset(tem, 0, sizeof(tem));
	n = ok = 0;

	for (int i = 0; i < 2; i++)
	    if (cnt[i] == cnt[2] || cnt[i] == cnt[2] - 1)
		ok = 1;

	if (ok){
	    ok = 0;

	    handle();

	    dfs(0);

	    if (ok > 1 )
		printf("ambiguous\n");
	    else if (ok == 1)
		printf("valid\n");
	    else
		printf("impossible\n");
	}
	else
	    printf("impossible\n");
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值