最後編輯時間: 2024/10/31

APCS 2024/10月 實作第一題解題思路

▌前言

現在來解 APCS 2024/10月 實作第一題 裝飲料 這題的題目
我的解法不會是最好的解法,但是是我下意識想出來的解法
因此雖然不會是最好的解法,但會是比較好理解好想出來的

▌題目

有一個杯子,可將其體積視為由兩個長方體組成(如下圖)

下方的長方體底面積為 w1×w1 cm²,高為 h1 cm
上方的長方體底面積為 w2×w2 cm²,高為 h2 cm。
一開始杯子為空。要裝 n 次飲料,每一次裝 v cm³ 容量的飲料
水杯滿水位不再上升問這n次倒飲料水位上升變化量最高幾 cm

▌想法

因為它題目的需求是將其他杯水倒進這個已知大小的容器裡面
並且這個已知容器有兩層w1×w1×h1和w2×w2×h2的大小
因此將水倒進去這裡我想到了六種可能性,可以用IF進行判斷
我當時先設一個z值為目前這個容器內已裝多少水的水面高度
第一種可能:h1未滿水倒進去後增加的高度 + z < h1
第二種可能:h1未滿水倒進去後增加的高度 + z > h1 且 < h2
第三種可能:h1未滿水倒進去後增加的高度 + z > h1  + h2
第四種可能:h1已滿水倒進去後增加的高度 + z < h1 + h2
第五種可能:h1已滿水倒進去後增加的高度 + z > h1 + h2
第六種可能:h1跟h2兩個容量都已滿,不用執行任何程式 
將這六種IF內增加加減乘除做運算之後,就能算出各種增加量
設定一個d值為歷史最高增加量,當這次增加量>d,替換d值
整個程式跑完後的d值即答案,第一次寫想法,有點抽象請見諒

▌整個程式

				
					#include <stdio.h>
int main(void) {
    int h1,h2,sl,i,z=0,d=0;
    long int w1,w2,zc,w;
    scanf("%d",&sl);
    long int a[sl];
    scanf("%ld%ld%d%d",&w1,&w2,&h1,&h2);
    w1 *= w1;
    w2 *= w2;
    for(i=0;i<sl;i++){
        scanf("%ld",&a[i]);
    }
    for(i=0;i<sl;i++){
        zc = a[i];
        if(z<h1){
            if(zc/w1+z<h1){
                if(zc/w1>d){
                    d = zc/w1;
                }
                z = z + zc/w1;
            }else{
                w=zc-(w1*h1-w1*z);
                if(w/w2>h2){
                    if(h1-z+h2>d){
                        d = h1-z+h2;
                    }
                    z = h1 + h2;
                }else{
                    if(h1-z+w/w2>d){
                        d = h1-z+w/w2;
                    }
                    z = h1 + w/w2;
                }
            }
        }else if(z<h1+h2){
            if(zc/w2+z>h2+h1){
                w = h2-(z-h1);
                if(w>d){
                    d = w;
                }
                z = h1 + h2;
            }else{
                if(zc/w2>d){
                    d = zc/w2;
                }
                z = z + zc/w2;
            }
        }
    }
    printf("%d",d);
    return 0;
}
				
			

▌程式講解

這前面資料型態以及宣告變數還有輸入數值我就不多做介紹了
現在注重於每杯水倒入的程式,不過FOR迴圈應該也不用介紹
直接從六種可能性開始講解,其中的六種可能性可以先分成三種
一種是h1未滿,一種是h1已滿但h2未滿,一種是h1和h2都滿
因此可以看到我程式FOR迴圈最初層的判斷式長這樣  (如下圖)

				
					if(z<h1){
    //程式
}else if(z<h1+h2){
    //程式
}
				
			

一開始先判斷h1未滿是否成立,不成立後判斷h2未滿是否成立
而h1+h2都滿即不需要執行程式,因此不用特別增加else程式
判斷完後假如h1未滿成立那可將第一、二、三種可能拿來判斷
首先判斷水倒進去後是否小於h1,如果小於直接算增加量即可
如果大於就判斷二三種可能性,如果後面倒進去的水不大於h2
就計算它在h1增加的量+它在h2增加的量就是這杯水的增加量
如果會大於h2,直接計算h1的增加量+h2的大小即是此增加量
三種可能寫完如果只有1個杯子答案會是正確的  (程式如下)

				
					//註:zc為當下要增加的水量
if(z<h1){
    if(zc/w1+z<h1){
        if(zc/w1>d){
            d = zc/w1;
        }
        z = z + zc/w1;
    }else{
        w=zc-(w1*h1-w1*z);
        if(w/w2>h2){
            if(h1-z+h2>d){
                d = h1-z+h2;
            }
            z = h1 + h2;
        }else{
            if(h1-z+w/w2>d){
                d = h1-z+w/w2;
            }
            z = h1 + w/w2;
        }
    }
}
				
			

再來就是寫判斷裡面已裝的水是否>h1且不大於h2的程式出來
就是前面的第四和第五種可能性,所以先判斷是否會>h1+h2
不大於的話直接寫計算倒進去的水在h2增加量的程式即可完成
大於的話計算h2-(z-h1)的值即是這次倒水的增加量,程式完工

				
					//註:zc為當下要增加的水量
if(z<h1+h2){
    if(zc/w2+z>h2+h1){
        w = h2-(z-h1);
        if(w>d){
            d = w;
        }
        z = h1 + h2;
    }else{
        if(zc/w2>d){
            d = zc/w2;
        }
        z = z + zc/w2;
    }
}
				
			

▌作者的話

第一次寫這種程式想法和程式介紹,寫得不好的地方請您見諒
希望這篇文章可以幫助到您,未來我會放更多更多的文章分享
我希望我的文章讓自己學習的同時也能幫助到別人,謝謝大家