UVa 196 Spreadsheet

这道题网上很多解题报告说用的是图论中的 dfs 或者是 topological sort

其实没有那么麻烦,题目的描述保证了cell的依赖关系不存在环 并且一定可解,所以直接利用递归思想一层层得找下去就行了,不需要拓扑排序,跟图论也没关系。 当然了 勉强可以解释为dfs.  


下面是我根据某人的博客改编的代码, 我对它进行了改进,对计算过的cell进行记录更新,这样避免了之后递归的重复计算,从这个意义上说,有点 动态规划的意味在里面。
此程序提交后的速度是0.1秒左右 排名160+   还算不错

代码如下
// uva 196
// thought from http://blog.csdn.net/moyan_min/article/details/8134658
// self-coded

#include<string>
#include<cstdio>
#include<iostream>
#include<cctype>
#include<cstdlib>
using namespace std;

struct Cell {
	bool isstr; // whether this cell is an expression string or integer value
	string strval;
	int intval;
};
Cell sheet[1010][1010];

int calculate(int i,int j) {
	if(sheet[i][j].isstr==false)
		return sheet[i][j].intval;
	// evaluate expression recursively
	else {
		Cell cell = sheet[i][j];
		int col=0,row=0;
		for(int k=1;k<cell.strval.size();k++) {
			if(isalpha(cell.strval[k]))
				col = col*26 + cell.strval[k] - 'A' + 1;
			else if(isdigit(cell.strval[k]))
				row = row*10 + cell.strval[k] - '0'; 
			else {
				cell.intval += calculate(row-1,col-1);// we start from 0 but the data is from 1, so need to substract 1
				col = row = 0;
			}
		}
		sheet[i][j] = cell;
		sheet[i][j].isstr = false; // we update every cell when we calculated them, this save future recursion time
		return cell.intval;
	}
}

int main() {
	int row,col,T;
	string str;
	scanf("%d",&T);
	while(T--) {
		scanf("%d %d",&col,&row);
		for(int i=0;i<row;i++)
			for(int j=0;j<col;j++) {
				cin>>str;
				if(str[0]=='=') {
					Cell cell;
					cell.isstr = true;
					cell.strval = str + "+"; // add an extra plus sign for recrusion convenience later
					cell.intval = 0;
					sheet[i][j] = cell;
				} else {
					Cell cell;
					cell.isstr = false;
					cell.intval = atoi(str.c_str());
					sheet[i][j] = cell;
				}
			}
		// start to evaluate
		for(int i=0;i<row;i++) {
			printf("%d",calculate(i,0));
			for(int j=1;j<col;j++) 
				printf(" %d",calculate(i,j));
			putchar('\n');
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值