LGOJ P1022 【计算器的改良 】

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

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

虽然很长但是很傻瓜

但其实就是很傻。

详情看注释

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

//#include "stdafx.h"
//#include <bits\stdc++.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;
}

原文地址:https://www.cnblogs.com/kion/p/11816254.html

时间: 2024-10-12 02:05:03

LGOJ P1022 【计算器的改良 】的相关文章

洛谷 P1022 计算器的改良

P1022 计算器的改良 题目背景 NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手ZL先生. 题目描述 为了很好的完成这个任务,ZL先生首先研究了一些一元一次方程的实例: 4+3x=8 6a-5+1=2-2a -5+12y=0 ZL先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数.小写字母及+.-.=这三个数学符号(当然,符号“-”既可作减号,也可作

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

题目背景 NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手ZL先生. 题目描述 为了很好的完成这个任务,ZL先生首先研究了一些一元一次方程的实例: 4+3x=8 6a-5+1=2-2a -5+12y=0 ZL先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数.小写字母及+.-.=这三个数学符号(当然,符号“-”既可作减号,也可作负号).方程中并没有括号,

洛谷——P1022 计算器的改良

https://www.luogu.org/problem/show?pid=1022#sub 题目背景 NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手ZL先生. 题目描述 为了很好的完成这个任务,ZL先生首先研究了一些一元一次方程的实例: 4+3x=8 6a-5+1=2-2a -5+12y=0 ZL先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数.

洛谷 P1022 计算器的改良 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1022 题目背景 NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手ZL先生. 题目描述 为了很好的完成这个任务,ZL先生首先研究了一些一元一次方程的实例: 4+3x=8 6a-5+1=2-2a -5+12y=

[NOIP2000] 计算器的改良

47. [NOIP2000] 计算器的改良 ★★   输入文件:computer.in   输出文件:computer.out   简单对比 时间限制:1 s   内存限制:128 MB 问题描述 NCL 是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手 ZL 先生.为了很好的完成这个任务 ,ZL 先生首先研究了一些一元一次方程的实例: 4+3x=8 6a-5+1=2-2

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

传送门 超级大模拟.. 代码 #include <cstdio> #include <cstring> #include <iostream> #define isword(x) ((x) >= 'a' && (x) <= 'z') int n, a1, b1, a2, b2, f, x; char s[1001], c; int main() { int i; scanf("%s", s + 1); n = strlen

NOIP2000普及组 T1计算器的改良

主要考字符串处理,把等式从等号中间断开,左边的区域为left,右边的区域为right. 开四个数组分别用来存储区域left和right中未知数的系数,区域left和right中的常数 先处理区域left,把区域left中含有未知数的数字和常数分别存储进数组,再处理区域right(字符串处理这里省略) 最后把存储区域left和right的未知数系数和常数的数组分别化简(合并同类项),进行平时解方程时候的模拟就好了. 主要看代码理解吧,思路讲的有点抽象了. 1 var 2 l_unk,r_unk,l

codevs 计算器的改良

#include<iostream> #include<cctype> #include<vector> #include<cstdio> using namespace std; // int get_num(string s) { int sum=0; for(int i=0;i<s.length();i++) { int k=s[i]-'0'; sum=sum*10+k; } //cout<<sum<<endl; retu

NOIP---2000---1

NOIP 2000 普及组                 题一   计算器的改良               (18分) 问题描述 NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手ZL先生.为了很好的完成这个任务,ZL先生首先研究了一些一元一次方程的实例: 4+3x=8 6a-5+1=2-2a  -5+12y=0 ZL先生被主管告之,在计算器上键入的一个一元一次方