Uva 1596
来源:互联网 发布:qq群发软件免费 编辑:程序博客网 时间:2024/06/03 23:43
一.题目
题目链接:Uva1596
二.思路
因为涉及到多个数组的嵌套,两个最近的[]是一对,先进先出,因此很明显是要用到栈的。我是用双栈来完成嵌套数组的处理的,核心思想就是从最里层的数组开始,计算出它的下标和数组名,判断是否有错误,有错误直接返回,没错误就继续让当前数组名该下标下的值成为下一个下标,然后获取新的数组名,直到栈空。数组的存储我是用map<string,map<int,int>>,来实现的,其中里层的map实现下标到值的映射,这样子判断一个下标是否已初始化就用map的count就可以实现,很快。之前其实使用map<string,vector<int>>来存取的,但是下标的最大值有2^31-1,判断是否初始化的时候直接TLE。。。还需要注意的是等式左右边进行判断的时候有小不同,左边外层不用判断是否初始化,右边需要,详情看代码注释。
三.程序源代码
#include <algorithm>#include <iostream>#include <map>#include <stack>#include <stdio.h>#include <vector>using namespace std;map<string, int> bound; //用来记录某个数组的sizemap<string, map<int, int> > elements; //记录某个数组已经初始化了的下标和值string line, name, lt, rt;int limit, index1, index2;stack<char> equation; //用栈来保存类似a[b[c[0]]]这样的等式并判断是否正确//判断下标是否越界,注意<0也是越界bool isOverflow(string n, int pos) { return (pos >= bound[n] || pos < 0); }//判断下标是否已初始化bool isInit(string name, int pos) { return (elements[name].count(pos) != 0); }bool isError(string e, int flag, int &num) { //flag参数用来判断是等号左边的数组还是右边的 //这个num是当前等号右边的值,如果等号右边没错,左边也没错的话,那么要更新等号左边数组的值为num if ((flag == 1) && (e.find('[') == e.npos)) { //如果右边不是个数组就是一个数字,更新num值,返回 //atoi函数是将一个c字符串转化成数字,头文件是stdio.h num = atoi(e.c_str()); return false; } while (!equation.empty())//清空栈 equation.pop(); for (int i = 0; i < e.length(); i++)//将当前的嵌套数组入栈 equation.push(e[i]); stack<char> st_temp; //双栈 string s_temp = ""; int pos; char temp1, temp2; while (!equation.empty()) {//不空就循环 temp1 = equation.top(); //弹出栈首 equation.pop(); if (temp1 != '[') //如果不是[,将该元素放到临时栈 st_temp.push(temp1); //保存数组名字 else { //如果是,从临时栈找到第一个]与等式栈的[匹配,两个[中间的字符就是数组名字 while (st_temp.top() != ']') { temp2 = st_temp.top(); st_temp.pop(); s_temp += temp2; } st_temp.pop(); //记得把]弹出 if (isalpha(s_temp[0])) { //因为最里层是一个数字,所以第一次的s_temp不是数组名而是下标,因此这里判断一下 if (isOverflow(s_temp, pos) || !isInit(s_temp, pos)) //如果有错,直接返回,没错。获取外层数组的下标 return true; else pos = elements[s_temp][pos]; } else //第一次s_temp是数字,保存 pos = atoi(s_temp.c_str()); s_temp = ""; }} while (!st_temp.empty()) {//获取最外层的数组的名字 temp2 = st_temp.top(); st_temp.pop(); s_temp += temp2; } if (flag == 1) { //如果是等号右边的等式,有错直接返回,没错就更新num值给左边 if (isOverflow(s_temp, pos) || !isInit(s_temp, pos)) return true; else num = elements[s_temp][pos]; } if (flag == 0) { //如果是右边,有错直接返回,没错更新数组的值 if (isOverflow(s_temp, pos)) return true; else elements[s_temp][pos] = num; } return false;}int main() { int n = 0, temp = 0, err_pos = 0, out = 0;//out用于判断退出程序时用的 bool flag = false; //是否有错 while (getline(cin, line)) { n++; if ((line[0] != '.') && !flag) { //如果一组数据里之前就有错了,那么剩下的都不用判断了,因为题目只要求记录第一次错误的行数 if (line.find("=") == line.npos) {//如果line不含等号,说明是个声明语句 index1 = line.find("["); name = line.substr(0, index1); limit = atoi(line.substr(index1 + 1, line.length() - index1 - 2) .c_str()); //要把左右两边的[]排除掉 bound.insert(make_pair(name, limit)); map<int, int> temp; elements.insert(make_pair(name, temp)); } else {//否则,将左右两边分离分别判断 index1 = line.find("="); lt = line.substr(0, index1); rt = line.substr(index1 + 1, line.length() - index1 - 1); //要注意一定要先执行判断右边的函数,获取到了右边的值,再判断左边,如果左边没错就把这个值赋给它 flag = (isError(rt, 1, temp) || isError(lt, 0, temp)); if (flag)//如果有错,记得行号 err_pos = n; } } if (line[0] == '.') { //如果是.,out+1,连续两个.会让out变成2,不连续则重置为0,是2就退出程序, out++; if (out == 2) break; if (flag) cout << err_pos << endl; else cout << 0 << endl; //记得把容器清空 n = 0; err_pos = 0; flag = false; temp = 0; bound.clear(); elements.clear(); while (!equation.empty()) equation.pop(); } else out = 0; } return 0;}
阅读全文
0 0
- UVA 1596
- Uva 1596
- UVa 1596 - Bug Hunt
- UVa 1596 - Bug Hunt
- UVa:1596 - Bug Hunt
- UVa-1596-Bug Hunt
- UVA 1596 Bug Hunt
- UVA 1596 Bug Hunt
- uva
- UVA
- UVA
- UVA
- uva
- UVA
- UVA
- UVA
- UVA
- UVA
- 打印正序的九九乘法表
- python 内置函数
- Codeforces896A Nephren gives a riddle
- 计算化学程序的实现:粒子数表象下波函数的表示
- MySQL 数据表管理
- Uva 1596
- java继承,子类构造方法赋值给父类对象
- android图文混排的几个实现思路
- 值得关注的机器学习博客
- EasyDemo*AlertDialog对话框(on Github)
- 轻量级微服务架构及最佳实践
- (easyUI)鼠标停留显示文字
- Linux_2 工具&进程
- 1042. 字符统计(20)