• 津津的储蓄计划 NOIp提高组2004


    这个题目当年困扰了我许久,现在来反思一下

    本文为博客园ShyButHandsome的原创作品,转载请注明出处

    右边有目录,方便快速浏览

    题目描述

    津津的零花钱一直都是自己管理。每个月的月初妈妈给津津(300)元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同。

    为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里,到了年末她会加上(20\%)还给津津

    因此津津制定了一个储蓄计划:每个月的月初,在得到妈妈给的零花钱后,如果她预计到这个月的月末手中还会有多于(100)元或恰好(100)元,她就会把整百的钱存在妈妈那里,剩余的钱留在自己手中。

    例如(11)月初津津手中还有(83)元,妈妈给了津津(300)元。津津预计(11)月的花销是(180)元,那么她就会在妈妈那里存(200)元,自己留下(183)元。

    到了(11)月月末,津津手中会剩下(3)元钱。

    津津发现这个储蓄计划的主要风险是,存在妈妈那里的钱在年末之前不能取出

    有可能在某个月的月初,津津手中的钱加上这个月妈妈给的钱,不够这个月的原定预算。如果出现这种情况,津津将不得不在这个月省吃俭用,压缩预算。

    现在请你根据(2004)(1)月到(12)月每个月津津的预算,判断会不会出现这种情况。

    如果不会,计算到(2004)年年末,妈妈将津津平常存的钱加上(20\%)还给津津之后,津津手中会有多少钱。

    输入格式

    (12)行数据,每行包含一个小于(350)的非负整数,分别表示(11)月到(12)月津津的预算。

    输出格式

    一个整数。如果储蓄计划实施过程中出现某个月钱不够用的情况,输出(-X)(X)表示出现这种情况的第一个月;

    否则输出到(2004)年年末津津手中会有多少钱。

    分析

    仔细阅读题目后,我的第一思路是模拟

    整体思路流程如下:

    1. 月初,妈妈给JJ钱
    2. 津津判断钱够不够花
    3. 月末,JJ的钱减去本月花了的钱(和给妈妈的钱,如果有的话)
    

    以下下分别是关键语句对应的伪代码

    伪代码:一种让人关注于算法本身而非实现的描述语言,没有固定语法,但要做到易懂

    • (12)个月:
      for month from 1 to 12
    • 每月月初,妈妈给津津(300)块钱:
      rest money add 300
    • 判断钱够不够花
      if rest_money - cost > 100
    • 给妈妈钱
      mother_money add (rest_money - rest_money mod 100)
    • 月末,结算
      rest = rest - the money was gived mother - cost

    代码实现

    (C)

    // 来源:洛谷题解
    // 作者:yangshizhuang
    #include <stdio.h>
    int main()
    {
        int n;
        int sum = 0;	        //初始化,用于记录每个月剩余有多少钱
        int sum0 = 0;	        //如果中间没有出现缺钱的情况,那么就用这个sum0来存储每个月在妈妈手里有多少钞票
        for (int i = 1; i <= 12; i++) //一年十二个月,不多做解释了
        {
            sum += 300;     //妈妈给钱
            scanf("%d", &n);
            sum = sum - n;
            if (sum < 0)     //如果消费大于开支则为负数,直接输出ok
            {
                printf("-%d
    ", i); //特别注意负号
                return 0;
            }
            else
                sum0 += sum / 100 * 100; //如果不是就往妈妈手里存钱
            sum = sum - sum / 100 * 100; //每个孩子手里剩余多少钱
        }
        printf("%d
    ", sum0 * 12 / 10 + sum); //如果上述未有输出,那么就可以打印输出多少钱了
        return 0;
    }
    

    (C++)

    // 来源:自己写的
    // 作者:@ShyButHandsome
    #include<bits/stdc++.h>
    using namespace std;
    
    int main(void)
    {
        int mother = 0;
        int rest = 0;
        const int ADD = 300;
        int cost = 0;
    
        for (int month = 0; month < 12; month++)
        {
            cin >> cost;
            rest += ADD;
            if (rest < cost)
            {
                cout << "-" << month + 1;
                // 直接结束程序运行
                return 0;
            }
            rest -= cost;
            if (rest > 100)
            {
                // 隐式类型转换
                mother += rest / 100 * 100;
                rest -= rest / 100 * 100;
            }
        }
        // 要加上手里还剩下的钱(+rest)
        double money = mother * 1.2 + rest;
        cout << money;
        return 0;
    }
    

    (Java)

    // 来源:洛谷题解
    // 作者:@TiMan
    import java.util.Scanner;
    
    public class Main {
        public static void main(String args[]) {
            int b, i, c = 0;
            int sum = 300;
            int x = 0;
            int m = 0;
            double ssum = 0;
            Scanner input = new Scanner(System.in);
            for (i = 1; i <= 12; i++) {
                int a = input.nextInt();
                if (sum < a && x == 0) {
                    x = i;
                } else {
                    b = sum - a;
                    if (b >= 100) {
                        c = b % 100;
                        m = m + b / 100; // m=1,
                        sum = c + 300;
                        ssum = c + m * 100 + m * 100 * 0.2;
                    } else {
                        sum = b + 300;
                        ssum = b + m * 100 + m * 100 * 0.2;
                    }
                }
            }
            if (x != 0) {
                System.out.println("-" + x);
            } else {
                System.out.println((int) ssum);
            }
    
        }
    }
    
    

    (Pascal)

    // 来源:洛谷题解
    // 作者:@川芎
    var
      y,s,x,i,g:longint;
    begin
      s:=0;
      g:=0;
      i:=1;
      while i<> 13 do
        begin
          readln(y);
          if y>300+s then              //如果钱不够了
            begin
              write('-',i); //输出预算大于资金的月份
              break;
            end
          else 
            g:=g+(((300+s-y) div 100)*100);//如预算小于资金,把钱给妈妈
          s:=(300+s-y) mod 100;//这是自己剩下的钱
          if (y<300+s) and (i=12) then 
            write(g*1.2+s:0:0);//最后加起来
          i:=i+1;
        end;
    end.
    

    (Python3)

    # 来源:自己写的
    # 作者:@ShyButHandsome
    mother = 0
    rest = 0
    
    for month in range(1, 13):
        cost = int(input())
        rest += 300
        if rest < cost:
            print(-month)
            exit()
        rest -= cost
        if rest > 100:
            # '//' 是整除而非注释
            mother += rest // 100 * 100
            rest -= rest // 100 * 100
        money = mother * 1.2 + rest
        print(money)
    

    总结

    其实现在来看,这个题目特别简单

    但当时就是一直不能(AC)

    困扰了我好久

    总结下这里踩过的几个坑

    年代久远,人老记忆力也不好了,可能总结的不是很全面

    欢迎补充你在做这个题目时

    遇到的问题(&)解决方案

    1. 不会做,没思路
      这题虽然是(NOIp)提高组,但实际上很简单
      如果你在做这题时感觉没有思路
      或者算法很复杂
      那么你可以多做做同类型(循环、模拟)的题目
      这类题目几乎都会对一个循环外的变量进行累加、累乘等
      比如这里的mother += rest / 100 * 100
    2. 代码看上去很好,但结果和答案总有那么点偏差
      这种情况可能是你赋予了了一些变量不属于他们类型的使命
      比如:整型除法(除数与被除数都是整型)结果也会是一个整型,而你想要小数
      计数器比预期的值少(1)
    3. 代码看上去很好,但结果和答案大相径庭
      这种情况可能是你的代码逻辑上出现了问题
      比如:
      ><写反了;
      少了某条语句;
      for循环是从0开始计数,而你使用时没有+1
      数组越界,等等;

    你问我为什么这么清楚?

    都是泪啊~

    参考资料

    洛谷P1089题解

    我是ShyButHandsome,一个名字与实际截然相反的OI蒟蒻,如果你觉得这篇文章写的还行的话,不妨点点推荐?

  • 相关阅读:
    新IO建立的聊天程序
    “万能数据库查询分析器”在四大软件下载网站的排行榜中均入围前10,可喜可贺
    命令行界面的C/S聊天室应用 (Socket多线程实现)
    URL 多线程下载
    DB 查询分析器 6.03 如何灵活、快捷地操作国产达梦数据库
    DB 查询分析器 6.03 在Windows 8 上安装与运行演示
    Maven部署项目到Tomcat
    中文版Maya基础培训教程
    Arduino技术指南
    Photoshop 淘宝店面设计从入门到精通
  • 原文地址:https://www.cnblogs.com/ShyButHandsome/p/12612798.html
Copyright © 2020-2023  润新知