Spreadsheet Calculator UVA - 215

给出一个R行C列的电子表格,行编号A~T, 列编号0~9,按照行优先的顺序给出各个单元格。每个单元格可能是整数也可能是引用了其他单元格的表达式,表达式仅由加减号、非负整数、单元格名称组成,没有括号,且以单元格名称开头,内部不含空白符,最多75个字符。要求计算出所有单元格的值,如果所有的单元格都能成功计算出结果,那么将这张表格输出来,每个元素6个占字符的宽度,对齐。如果出现单元格循环引用以致无法输出,则将无法正常计算出结果的单元格及其表达式输出,仍按照行优先的顺序输出。详细格式参见样例。

关键是陷入循环结构的处理,类似拓扑排序
但是在输出格式与处理字符串输入(没有意识到字符串中多位数字被拆)耗费大量时间

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cctype>
#include<vector>
#include<cmath>
#include<iomanip>
using namespace std;
const int maxr = 25;
const int maxc = 15;
const int INF = 1e5;  //代替错误指示符号
int sheet[maxr * maxc];
int done[maxr * maxc];
vector<int> G[maxr * maxc];
string s[maxr * maxc];
int dfs(int u)
{
    done[u] = -1;
    for (int i = 0; i < G[u].size(); i++)
    {
        int v = G[u][i];
        int sign = 1;
        if (v < 0)
        {
            sign = -1;
            v = -v;
        }
        if (done[v] < 0)
            return INF;
        else if (done[v])
        {
            sheet[u] += sign * sheet[v];
            continue;
        }
        int ans = dfs(v);
        if (ans == INF)
        {
            return INF;
        }
        else
            sheet[u] += sign * ans;
    }
    done[u] = 1;
    return sheet[u];
}

int main()
{
    int R, C;

    while (scanf("%d %d", &R, &C) && R)
    {
        memset(sheet, 0, sizeof(sheet));
        memset(G, 0, sizeof(G));
        memset(done, 0, sizeof(done));
        int cnt = 0;  //二维化一维进行编号
        for (int i = 1; i <= R*C;i++)//输入与建图
        {
            cin >> s[i];
            cnt++;
            if (s[i].size() == 1)
            {
                sheet[cnt] += s[i][0] - '0';
            }
            else
            {
                int n, m, flag = 0, flag1 = 1, num;
                for (int j = 0; j < s[i].size(); j++)
                {
                    if (isalpha(s[i][j]))
                    {
                        n = s[i][j] - 'A';
                        flag = 1;
                    }
                    else if (isdigit(s[i][j]) && flag)
                    {
                        m = s[i][j] - '0';
                        flag = 0;
                        num = C*n + m + 1;
                        G[cnt].push_back(flag1 * num);  //G储序号,负数代表此运算符号
                    }
                    else if (s[i][j] == '-')
                    {
                        flag1 = -1;
                    }
                    else if (s[i][j] == '+')
                    {
                        flag1 = 1;
                    }
                    else if (isdigit(s[i][j]) && !flag)
                    {
                        int k = 1, num = 0;
                        num += (s[i][j] - '0');
                        while (isdigit(s[i][j + 1]))//注意字符串中数字不止一位数时
                        {
                            num = num * pow(10, k) + (s[i][j + 1] - '0') ;//sheet储子叶带符号值
                            j++;
                            k++;
                        }
                        sheet[cnt] += flag1 * num;
                    }
                }
            }
        }
        int flag = 1, ans;
        for (int i = 1; i <= R*C; i++)
        {
            if (!done[i])
            {
                ans = dfs(i);
                if (ans == INF)
                {
                    printf("%c%d: ", (i-1) / C + 'A', (i-1)%C);
                    cout << s[i] << endl;
                    flag = 0;
                }
            }
            else if (done[i] == -1)
            {
                printf("%c%d: ", (i - 1) / C + 'A', (i - 1) % C);
                cout << s[i] << endl;
            }
        }
        if (flag)
        {
            cout << " ";
            for (int i = 0; i < C; i++)
            {
                cout << std::right << setw(6) <<i;  //对齐
            }
            cout << endl;
            cnt = 0;
            for (int i = 0; i < R; i++)
            {
                printf("%c",'A' + i);
                int first = 1;
                for (int j = 0; j < C; j++)
                {
                    cout << std::right << setw(6) <<sheet[++cnt];
                }
                cout << endl;
            }
        }
        cout << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值