LGOJ P1022 计算器的改良

Posted kion

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LGOJ P1022 计算器的改良 相关的知识,希望对你有一定的参考价值。

依然是自带大常数的(STL)

于是乎就有了这个很长的代码

虽然很长但是很傻瓜

但其实就是很傻。

详情看注释

// P1022.cpp: 定义控制台应用程序的入口点。
//

//#include "stdafx.h"
//#include <bitsstdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <list>
#include <cmath>
#include <cctype>
#include <cstdlib>


using namespace std;
list<char> L, L1, L2;
double unk = 0;//未知数的系数
c = 0;//常数项
char unkw;//未知数的字母,因为本题的字母不确定所以要单独记录
int yes = 1;//↑跟unkw有关的一个参数

void intial()//初始化
{
    if (L.front() != '+' && L.front() != '-')
    {
        L.push_front('+');//为了整齐划一所以要加‘+’
    }
    int flag = 0;
    //↓要十分注意,在我们的习惯中未知数的系数如果是1的话是可以省略的
    //↓这是本题一个坑点
    for (list<char>::iterator it = L.begin(); it != L.end(); it++)
        if (*it >= 'a'&&*it <= 'z')
        {
            it--;
            if (*it<'0' || *it>'9')
            {
                it++;
                L.insert(it, '1');
                it--;
            }
            it++;
        }
        //↓把等号左右两边的东西分开放更加直观而方便
    for (list<char>::iterator it = L.begin(); it != L.end(); it++)
    {

        if (*it == '=')
        {
            flag = 1;
            it++;
            if (*it != '+' && *it != '-')
            {
                L.insert(it, '+');
                //为所有的正数加个‘+’,判断更加方便
            }
            it--;
        }
        if (flag == 0)
        {
            L1.push_back(*it);
            //左边的东西放L1
        }
        if (flag == 1)
        {
            L2.push_back(*it);
            //右边的东西放L2
        }
    }
    L1.push_back('+');
    L2.push_back('+');
    //判断的时候是取两个符号之间的数的,所以要在末尾补上符号
}

void debug()//这个只是用来调试的
{
    cout << "left:";
    for (list<char>::iterator it = L1.begin(); it != L1.end(); it++)
        cout << *it;
    cout << endl << "right:";
    for (list<char>::iterator it = L2.begin(); it != L2.end(); it++)
        cout << *it;
    cout << endl;
}

int ltoi(list<char> tlist)//从list到int的函数
{
    int ans = 0;
    int i = 1;
    int minus = 0;
    if (tlist.front() == '-')minus = 1;//判断数字正负
    tlist.reverse();//反转过来计算更方便
    for (list<char>::iterator it = tlist.begin(); it != tlist.end(); it++)
    {
        if (*it >= '0'&&*it <= '9')
        {
            ans += ((*it) - '0')*i;
            i *= 10;//累加
        }
    }
    return minus ? (-ans) : (ans);
}

void deal(list<char> tlist)//分离未知数和常数
{
    if (tlist.back() >= '0'&&tlist.back() <= '9')
    {
        c += ltoi(tlist);//这个项是常数,加到c里面
    }
    else
    {
        unk += ltoi(tlist);//这个项含有未知数,累加到未知数里面
        if (yes)
        {
            unkw = tlist.back();
            yes = 0;
            //记得把未知数是啥记录下来
        }
    }
}

void judge()//处理等号左边的东西
{
    int cnt = 0;//萌萌哒计数器
    list<char> curr;//记录当前项
    list<char>::iterator left, right;//区间左右地址记录
    for (list<char>::iterator it = L1.begin(); it != L1.end(); it++)
    {
        if (*it == '+' || *it == '-')
        {
            cnt++;
            if (cnt == 1)//左边有符号,记录
            {
                left = it;
            }
            if (cnt == 2)//右边有符号,记录
            {
                right = it--; //it++;
                curr.assign(left, right);//于是我们得到了一项
                cnt = 0;
                deal(curr);//处理项
                curr.clear();//清零
            }
        }
    }


}

void judge2()//对于右边东西的判定,大体与judge()相同
{
    int cnt = 0;
    list<char> curr;
    list<char>::iterator left, right;
    for (list<char>::iterator it = L2.begin(); it != L2.end(); it++)
    {
        if (*it == '+' || *it == '-')
        {
            cnt++;
            if (cnt == 1)
            {
                left = it;
            }
            if (cnt == 2)
            {
                right = it--; //it++;
                curr.assign(left, right);
                if (curr.front() == '+')//这里开始↓
                {
                    curr.pop_front();//
                    curr.push_front('-');//
                }
                else
                {
                    curr.pop_front();//
                    curr.push_front('+');//↑到这里,是移项
                }
                cnt = 0;
                deal(curr);
                curr.clear();
            }
        }
    }
}

int main()
{
    string str;
    cin >> str;//字符串读入就懒得写个循环了
    for (int i = 0; i < str.length(); i++)
    {
        L.push_back(str[i]);//然而还是要循环....
    }
    intial();

    //debug();
    judge();
    judge2();
    double x = 0;
    x = -(c / unk);
    if (x == 0)x = abs(x);//注意对-0.000特殊处理,坑点!
    cout << c << ' ' << unk << endl;
    cout << unkw << '=';
    printf("%.3f", x);//保留三位

    return 0;
}

以上是关于LGOJ P1022 计算器的改良 的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1022 计算器的改良

洛谷—— P1022 计算器的改良

洛谷——P1022 计算器的改良

洛谷 P1022 计算器的改良 题解

[NOIP2000] 提高组 洛谷P1022 计算器的改良

[luoguP1022] 计算器的改良(模拟)