洛谷P2108 学英语

一道字符串+模拟的洛谷橙题,题面如下:

不得不说,这道题的样例真滴良心^_^,帮我们把所有的坑都填上力!那么剩下就靠自己稳步前进啦!

解题:

  1. 读取信息

题目给出的数据可以看作一段一段的字符串,不妨用vector<string>容器储存,如下方法输入:

vector<string>v;
string s;
while(cin>>s)v.push_back(s);

注:本题如果用getline(),可能会导致判题出错!

  1. 字符串的比较

为了判断每一段字符分别是什么,一定避免不了字符串之间的比较啦~

c++的string已经重载了==运算符,我们便可通过如下方法简单地比较字符串是否相等:

string s
if ( s == "one" )

  1. 量词

本题的量词有“hundred”、“thousand”、“million”

对于类似eight thousand six hundred的输入,想要得到8600的答案输出,我们必须对量词前的数据加以记录,再使该数据乘上对应的量,加入到答案ans中,再将memo置0,

例:

读取字串eight时,记录memo=8,

读取thousand时,8×1000=8000,ans+=8000,memo=0;

读取字串six时,记录memo=6,

读取hundred时,6×100=600,ans+=600,memo=0;

经过上述结果,我们便轻松地得到正确答案ans=8600。

然鹅,橙题并不应该这么简单……

样例4:

eight hundred fourteen thousand twenty two = 814022

在样例4中,我们看到了量词的叠加,几百个的几千,假如用我们刚才的那套算法,memo在遇到hundred时就被置空了,便无法实现让thousand的量词memo = 800+14

为应对此问题,遍历过程中,我们可以搜索第i个元素后面有没有符合作为量词条件的字符串,如果有,我们应该用memo将其记录,如果没有,我们应该直接加入ans中。

模拟:对于样例4: eight hundred fourteen thousand twenty two

v[0]=eight 后面有量词hundred memo+=8

v[1]=hundred 后面有量词thousand memo*=100 (memo=800)

v[2]=fourteen 后面有量词thousand memo+=14 (memo=814)

v[3]=thousand 后面无量词 ans+=memo*1000 (ans=814000) memo=0

v[4]=thousand 后面无量词 ans+=20 (ans=814020) memo=0

v[5]=thousand 后面无量词 ans+=2 (ans=814022) memo=0

注:

据题意,我们知道输入符合数字的语法规范,即只能有A hundred B thousand,“几百个千”,

而不能有“几千个百”而引起歧义。

对于类似eight thousand six hundred的输入,应该在搜索thousand后的量词时,回避hundred

AC代码如下:

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>

using namespace std;

vector<string> v; //储存所有字符串的容器

int ans = 0;  //答案 
int sign = 0; //0默认为正  1为负

bool judge(int t)//判断t位置后是否有合法量词
{
    int ret = 0;
    if (v[t] == "million")return true; //不会有million million,并且million不可能作为hundred/thousand的数词
    if (v[t] == "thousand")ret = 1;//过滤hundred,因为正确的说法是几百个千,而不是几千个百

    for (int i = t + 1; i <= v.size() - 1; i++)
    {
        if (v[i] == "hundred")ret -= 1;
        if (v[i] == "million" || v[i] == "thousand")
            return false;  //后续有量词
    }
    if (ret >= 0)
        return true;   //后续没有量词
    else return false; //后续有量词
}

int main()
{
    string s;
    while(cin>>s)v.push_back(s);

    int memo = 0;      //用于储存上一个输入的数字,便于对其进行hundred、thousand等操作
    for (int i = 0; i <= v.size() - 1; i++) //遍历获取的每个字符串
    {
        if (v[i] == "negative") {sign = 1; continue;}//负数
        int temp = 0;  //临时储存数据

        /* 1---9 需要用memo记录,应对one hundred等情况 */
        if (v[i] == "one") { temp = 1; }
        if (v[i] == "two") { temp = 2; }
        if (v[i] == "three") { temp = 3; }
        if (v[i] == "four") { temp = 4; }
        if (v[i] == "five") { temp = 5; }
        if (v[i] == "six") { temp = 6; }
        if (v[i] == "seven") { temp = 7; }
        if (v[i] == "eight") { temp = 8; }
        if (v[i] == "nine") { temp = 9; }
        /* 10---90  */
        if (v[i] == "ten") { temp = 10; }
        if (v[i] == "eleven") { temp = 11; }
        if (v[i] == "twelve") { temp = 12; }
        if (v[i] == "thirteen") { temp = 13; }
        if (v[i] == "fourteen") { temp = 14; }
        if (v[i] == "fifteen") { temp = 15; }
        if (v[i] == "sixteen") { temp = 16; }
        if (v[i] == "seventeen") { temp = 17; }
        if (v[i] == "eighteen") { temp = 18; }
        if (v[i] == "nineteen") { temp = 19; }
        if (v[i] == "twenty") { temp = 20; }
        if (v[i] == "thirty") { temp = 30; }
        if (v[i] == "forty") { temp = 40; }
        if (v[i] == "fifty") { temp = 50; }
        if (v[i] == "sixty") { temp = 60; }
        if (v[i] == "seventy") { temp = 70; }
        if (v[i] == "eighty") { temp = 80; }
        if (v[i] == "ninety") { temp = 90; }
        /* 量词  直接对之前记忆的数据进行操作即可  */
        if (v[i] == "hundred") { memo *= 100; }
        if (v[i] == "thousand") { memo *= 1000; }
        if (v[i] == "million") { memo *= 1000000;  }

        //判断后续是否有合法量词    | 若有,则加入memo,否则加入ans
        if (judge(i))  //没有合法量词,答案直接加上,再把memo置空
        {
            ans += memo + temp;
            memo = 0;
        }
        else             //有量词,不选择直接加ans里,而加入memo记忆储存
        {
            memo += temp;
        }
    }

    if (sign == 1)cout << "-";
    cout << ans << endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值