题意:两个问题,一是:问你是否满足罗马数字的等式,二是:是否有阿拉伯数字满足等式,第一个问题的注意点是:如果后一个的字符所代表的数字比它大,那么这个字符将是减去的,而不是加,第二个问题:我是把所有出现的字符都记录下来,然后就是一个个的搜索,注意的是:第一个不能是零
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 30;
char str[MAXN];
char str_path[MAXN][MAXN];
char kind_str[MAXN];
int path_num,val[100];
int path_val[MAXN],sign,kind;
int vis[10];
int hash[100];
int Vkind[100];
void init()
{
int len = strlen(str);
int cnt = 0;
str[len] = '+';
int t = 0;
path_num = 0;
kind = 0;
for (int i = 0; i <= len; i++)
{
if (str[i] != '+' && str[i] != '=')
{
str_path[path_num][cnt++] = str[i];
path_val[path_num] += val[str[i]];
if (!hash[str[i]]) // 储存所有出现的字符
{
kind_str[kind] = str[i];
kind++;
hash[str[i]] = 1;
}
if (val[str[i]] > t)
path_val[path_num] -= 2 * t;
t = val[str[i]];
}
else
{
str_path[path_num][cnt] = '\0';
t = 0;
path_num++;
cnt = 0;
}
}
}
int judge()
{
int sum=0;
for (int i = 0; i < path_num-1; i++)
sum += path_val[i];
if (sum == path_val[path_num-1])
return 1;
else return 0;
}
void dfs(int cur)
{
if (sign == 2)
return;
if (cur >= kind)
{
int Vnum[path_num];
memset(Vnum,0,sizeof(Vnum));
for (int i = 0; i < path_num; i++)
for(int j = 0; j < strlen(str_path[i]); j++)
Vnum[i] = Vnum[i] * 10 + Vkind[str_path[i][j]];
int sum = 0;
for (int i = 0; i < path_num - 1; i++)
sum += Vnum[i];
if (sum == Vnum[path_num-1])
sign++;
return ;
}
for (int i = 0; i <= 9; i++)
{
if (cur == 0 && i == 0)
continue;
if (!vis[i])
{
vis[i] = 1;
Vkind[kind_str[cur]] = i; // 储存字符所表示的数字
dfs(cur+1);
vis[i] = 0;
}
}
}
int main()
{
val['I']=1,val['V']=5,val['X']=10,val['L']=50,val['C']=100;
val['D']=500,val['M']=1000;
while (scanf("%s",str) != EOF && str[0] != '#')
{
memset(vis,0,sizeof(vis));
memset(hash,0,sizeof(hash));
memset(path_val,0,sizeof(path_val));
init();
int flag = judge();
if (flag)
printf("Correct ");
else printf("Incorrect ");
sign = 0;
dfs(0);
if (sign == 0)
printf("impossible\n");
else if (sign == 1)
printf("valid\n");
else printf("ambiguous\n");
}
return 0;
}