欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-18 18:53:52
这个题目当年困扰了我许久,现在来反思一下本文内含多种代码实现 ......

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

本文为博客园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\n", i); //特别注意负号
		    return 0;
		}
		else
		    sum0 += sum / 100 * 100; //如果不是就往妈妈手里存钱
		sum = sum - sum / 100 * 100; //每个孩子手里剩余多少钱
	}
	printf("%d\n", 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. 代码看上去很好,但结果和答案总有那么点偏差
    这种情况可能是你赋予了了一些变量不属于他们类型的使命
    比如:整型除法(除数与被除数都是整型)结果也会是一个整型,而你想要小数
  3. 代码看上去很好,但结果和答案大相径庭
    这种情况可能是你的代码逻辑上出现了问题
    比如:
    ><写反了;
    少了某条语句;
    for循环是从0开始计数,而你使用时没有+1
    数组越界,等等;

你问我为什么这么清楚?

都是泪啊~

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