习题6-13 电子表格计算器(Spreadsheet Calculator, ACM/ICPC World Finals 1992, UVa215)

思路:dfs判环并求解每个单元格的数值。
注意:字符串的处理,负数的判断。

先特判了第一个字符。dfs写的有些丑陋。。。

更好的思路是以数字字母来分割字符串,无需特判。

#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <utility>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <cctype>
#define CLEAR(a, b) memset(a, b, sizeof(a))
#define IN() freopen("in.txt", "r", stdin)
#define OUT() freopen("out.txt", "w", stdout)
#define LL long long
#define maxn 25
#define maxm 15
#define mod 1000000007
#define INF 1000000007
#define eps 1e-5
#define PI 3.1415926535898
using namespace std;
//-------------------------CHC------------------------------//
const int LEN = 80;
int R, C;
char G[maxn][maxm][LEN];
int val[maxn][maxm];
int vis[maxn][maxm];
typedef char str[LEN];
bool have_circle;

int find(str s, int pos) {
	int len = strlen(s);
	for (int i = pos; i < len; ++i)
		if (s[i] == '+' || s[i] == '-') return i;
	return len;
}

int dfs(int r, int c) {
	if (val[r][c] != INF) return val[r][c];
	vis[r][c] = -1;
	str &s = G[r][c];
	int len = strlen(s);
	int i = 0;
	int pos = find(s, i);
	if (pos == 0) {
		pos = find(s, pos + 1);
		val[r][c] = atoi(s + i);
	}
	else {
		if (isdigit(s[i])) val[r][c] = atoi(s + i);
		else {
			int r1 = s[0] - 'A', c1 = s[1] - '0';
			if (vis[r1][c1] == -1) {
				have_circle = true;
				return INF;
			}
			if ((val[r][c] = dfs(r1, c1)) == INF) return INF;
		}
	}
	i = pos + 1;
	while (i < len) {
		char op = s[i - 1];
		pos = find(s, i);
		if (isdigit(s[i])) {
			if (op == '+') val[r][c] += atoi(s + i);
			else val[r][c] -= atoi(s + i);
		}
		else {
			int r1 = s[i] - 'A', c1 = s[i + 1] - '0';
			if (vis[r1][c1] == -1) {
				have_circle = true;
				val[r][c] = INF;
				return INF;
			}
			int temp = dfs(r1, c1);
			if (temp == INF) {
				val[r][c] = INF;
				return INF;
			}
			if (op == '+') val[r][c] += temp;
			else val[r][c] -= temp;
		}
		i = pos + 1;
	}
	vis[r][c] = 1;
	return val[r][c];
}

void print1() {
	putchar(' ');
	for (int i = 0; i < C; ++i) printf("%6d", i);
	puts("");
	for (int i = 0; i < R; ++i) {
		putchar('A' + i);
		for (int j = 0; j < C; ++j)
			printf("%6d", val[i][j]);
		puts("");
	}
}

void print2() {
	for (int i = 0; i < R; ++i)
		for (int j = 0; j < C; ++j)
			if (val[i][j] == INF)
				printf("%c%c: %s\n", 'A' + i, '0' + j, G[i][j]);
}

void solve() {
	CLEAR(vis, 0);
	have_circle = false;
	for (int i = 0; i < R; ++i) {
		for (int j = 0; j < C; ++j)
			if (val[i][j] == INF)
				dfs(i, j);
	}
	if (!have_circle) print1();
	else print2();
	puts("");
}

int main() {
	while (~scanf("%d%d", &R, &C)) {
		if (R == 0 && C == 0) break;
		for (int i = 0; i < R; ++i) {
			for (int j = 0; j < C; ++j) {
				scanf("%s", G[i][j]);
				val[i][j] = INF;
			}
		}
		solve();
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值