這個題目當年困擾了我許久,現在來反思一下
本文為博客園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\)
困擾了我好久
總結下這里踩過的幾個坑
年代久遠,人老記憶力也不好了,可能總結的不是很全面
歡迎補充你在做這個題目時
遇到的問題\(\&\)解決方案
- 不會做,沒思路
這題雖然是\(NOIp\)提高組,但實際上很簡單
如果你在做這題時感覺沒有思路
或者演算法很復雜
那么你可以多做做同型別(回圈、模擬)的題目
這類題目幾乎都會對一個回圈外的變數進行累加、累乘等
比如這里的mother += rest / 100 * 100, - 代碼看上去很好,但結果和答案總有那么點偏差
這種情況可能是你賦予了了一些變數不屬于他們型別的使命
比如:整型除法(除數與被除數都是整型)結果也會是一個整型,而你想要小數
計數器比預期的值少\(1\), - 代碼看上去很好,但結果和答案大相徑庭
這種情況可能是你的代碼邏輯上出現了問題
比如:
>和<寫反了;
少了某條陳述句;
for回圈是從0開始計數,而你使用時沒有+1;
陣列越界,等等;
你問我為什么這么清楚?
都是淚啊~
參考資料
洛谷P1089題解
我是ShyButHandsome,一個名字與實際截然相反的OI蒟蒻,如果你覺得這篇文章寫的還行的話,不妨點點推薦?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/4980.html
標籤:C++
上一篇:連續出現的字符
下一篇:C++ 公有派生
