uva :185 - Roman Numerals(dfs)

题目:uva :185 - Roman Numerals

题目大意:给出一个字符串的等式,问这个字符串是否是罗马等式吗?有符合的阿拉伯等式吗?前者是就输出correct or incorrect ,后者就得分情况:

ambiguous 能组成阿拉伯等式的字母组合大于等于2,
valid     能组成阿拉伯等式的字母组合只有1种
impossible 没有符合阿拉伯等式的字母组合。

解题思路:
1、能不能组成罗马等式的规则:每个当前的字母(i)的左边的字母((i-1)所对应的值如果比i所对应的值小的话,i-1的值就取负值,否则就取正值。最后判断是否等是式左右成立。
2、能不能组成阿拉伯等式的话,就是每个字母都可以用 0 - 9 之间的数字去替代,看是否有是左右两边等式成立的。
注意:
0单独出现,和出现前导0的情况,都是不要的,需要排除。然后相同的字母表示一样的值。这里就将每个字母的情况都枚举出来,然后去掉0出现错误的情况,dfs()找出符合的组合。

代码:

#include <stdio.h>
#include <string.h>

const int N = 10;

char str[N * N], s1[3][N];
int s[N * N];
char vis[N * N], head[N * N];
const char *letter = "IVXLCDM";
int	count, size;

void init () {

	s[‘I‘] = 1;
	s[‘X‘] = 10;
	s[‘C‘] = 100;
	s[‘M‘] = 1000;
	s[‘V‘] = 5;
	s[‘L‘] = 50;
	s[‘D‘] = 500;
	size = 0;
}

int trans (char * a) {

	int num = 0, i;
	for (i = 1; i <= strlen (a); i++) {

		if (s[a[i - 1]] >= s[a[i]])
			num += s[a[i- 1]];
		else
			num -= s[a[i - 1]];
	}
	return num;
}

bool is_roman () {

	int n1 = trans(s1[0]);
	int n2 = trans(s1[1]);
	int n3 = trans(s1[2]);
	if (n1 + n2 == n3)
		return true;
	return false;
}

int tran_num (char * a) {

	int num = 0;
	for (int i = 0; i < strlen (a); i++)
		num = num * 10 + s[a[i]];
	return num;
}

void is_numerals (int n, int v) {

	if (n == size) {

		int n1 = tran_num (s1[0]);
		int n2 = tran_num (s1[1]);
		int n3 = tran_num (s1[2]);
		if (n1 + n2 == n3)
			count++;
		return ;
	}
	if (v >= 7)
		return;
	while(!vis[letter[v]])
		v++;
	if (v < 7) {
		for (int j = 0; j < 10; j++) {

			if (j == 0 && head[letter[v]])
				continue;
			s[letter[v]] = j;
			is_numerals (n + 1, v + 1);
			if (count >= 2)
				return;
		}
	}
}

int main () {

	int k, j;
	while (scanf ("%s", str) , str[0] != ‘#‘) {

		init();
		k = j = 0;
		memset (vis, 0, sizeof (vis));
		memset (head, 0, sizeof (head));
		for (int i = 0; i < strlen (str); i++) {

			if (str[i] != ‘+‘ && str[i] != ‘=‘ ) {

				s1[k][j++] = str[i];
				if (!vis[str[i]])
					size++;
				vis[str[i]] = 1;
				if (j == 1)
					head[str[i]] = 1;
			} else {

				s1[k][j] = ‘\0‘;
				k++;
				j = 0;
			}
		}
		s1[2][j] = ‘\0‘;
		printf ("%s ", is_roman() ?"Correct":"Incorrect");

		count = 0;
		is_numerals(0, 0);

		if (!count)
			printf ("impossible\n");
		else {

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

uva :185 - Roman Numerals(dfs)

时间: 2024-10-09 19:59:29

uva :185 - Roman Numerals(dfs)的相关文章

【UVa】208 Firetruck(dfs)

题目 题目 ? ? 分析 一开始不信lrj的话,没判联通,果然T了. 没必要全部跑一遍判,只需要判断一下有没有点与n联通,邻接表不太好判,但无向图可以转换成去判n与什么联通. 关于为什么要判,还是因为数据造的强,造了许多之前的节点情况巨多,然而所有节点都不和中点连接的情况...... ? ? 代码 #include <bits/stdc++.h> using namespace std; int n; vector<int> G[100]; vector<int> An

uva :10123 - No Tipping(dfs + 几何力距 )

题目:uva :10123 - No Tipping 题目大意:给出l, m, n 分别表示 长度为l 的杠杆, 重量为 m, 有n个物体放在上方.问每次从上面挑选一个物品移除,是否能使杠杆继续平衡.这个过程中都可以的话,就输出移除顺序(不唯一) 否则就输出 impossible ,一开始,这个杠杆就不平衡的情况也会是有的.因为杠杆也是有重量的. 解题思路; 1.这题先前我就不明白什么怎么样的情况下,双支撑点的杠杆不平横,后面看了别人的报告才明白. 首先  我这里有两个支撑点 (1, 2) 左边

UVA 572 -- Oil Deposits(DFS求连通块+种子填充算法)

UVA 572 -- Oil Deposits(DFS求连通块) 图也有DFS和BFS遍历,由于DFS更好写,所以一般用DFS寻找连通块. 下述代码用一个二重循环来找到当前格子的相邻8个格子,也可用常量数组或者写8条DFS调用. 下述算法是:种子填充(floodfill) 两种连通区域 四连通区域:从区域内一点出发,可通过上.下.左.右四个方向的移动组合,在不越出区域的前提下,能到达区域内的任意像素 八连通区域:从区域内每一像素出发,可通过八个方向,即上.下.左.右.左上.右上.左下.右下移动的

UVA 580 - Critical Mass(DP)

题目链接:580 - Critical Mass 题意:一个栈,里面可以放L和U,有三个连续的U就是不安全的,问共有几种不安全的情况 思路:dp,dp[i][j][k],表示放到第i个,最后两个状态为j,k表示有没有出现不安全.然后去记忆化搜索一下就可以了 然后还有一种做法是,先考虑安全的情况,在用总情况(1<<n 种)减去安全的情况,安全的情况的递推方式很容易dp[i]表示放第i个, dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]. 不过这题都没给数据范围

POJ 3087 Shuffle&#39;m Up (DFS)

题目链接:Shuffle'm Up 题意:有a和b两个长度为n的字符序列,现定义操作: 将a.b的字符交叉合并到一个序列c,再将c最上面的n个归为a,最下面n个归为b 给出a,b和目标序列c,问最少多少次操作a.b转化为c 解析:将a.b放入哈希表,然后模拟操作过程直接dfs即可. AC代码: #include <cstdio> #include <iostream> #include <cstring> #include <map> using names

LeetCode Subsets (DFS)

题意: 给一个集合,有n个互不相同的元素,求出所有的子集(包括空集,但是不能重复). 思路: DFS方法:由于集合中的元素是不可能出现相同的,所以不用解决相同的元素而导致重复统计. 1 class Solution { 2 public: 3 vector<vector<int>> subsets(vector<int>& nums) { 4 sort(nums.begin(),nums.end()); 5 DFS(0,nums,tmp); 6 return a

POJ 1699 Best Sequence(DFS)

題目鏈接 題意 : 將幾個片段如圖所示方法縮成一個序列,求出最短這個序列. 思路 : 其實我也不知道怎麼做.....看網上都用了DP.....但是我不會.....這個DP不錯,還有用KMP+状压DP做的 1 //1699 2 #include <iostream> 3 #include <stdio.h> 4 #include <string.h> 5 #include <string> 6 7 using namespace std; 8 9 string

UVA 618 - Doing Windows(数论)

题目链接:618 - Doing Windows 题意:给定一个大小不能变的屏幕,和四个大小可以变的窗口,变化要保持长宽比,问这四个窗口能不能调整后全部放下正好填满屏幕,不能重叠 思路:情况一共就几种:4个叠一起,3个叠一起+一个,2个和2个,一个和两个叠一起在一个,把这几种情况全判断了就可以了,判断过程利用gcd,lcm可以求边长. 代码: #include <stdio.h> #include <string.h> long long gcd(long long a, long

LeetCode Subsets II (DFS)

题意: 给一个集合,有n个可能相同的元素,求出所有的子集(包括空集,但是不能重复). 思路: 看这个就差不多了.LEETCODE SUBSETS (DFS) 1 class Solution { 2 public: 3 vector<vector<int>> subsets(vector<int>& nums) { 4 sort(nums.begin(),nums.end()); 5 DFS(0,nums,tmp); 6 ans.push_back(vector