ZeroJudge f163-貨物分配 解題心得( 題目 )
解題概念:遞迴
解題方法:這題其實就是一連串遞迴,先遞迴求左右分別的重量以利比較,接著放貨物的時候就遞迴放貨物放到葉節點。
注意:這題要使用自己寫的方式輸入不能使用readline().split(" "),否則很容易MLE (感謝jam930725@gmail.com(浮沉沉沉沉沉沉沉沉)提醒)
參考程式碼( 如果有更好意見可在下方留言,以做為本文章之補充,感謝! ):
//Author:En Chi Tsung(欉恩祁)
//Date:2021/10/06
import java.io.*;
public class zjf163 {
public static int ret,r,w,n,m;
public static int[] ow,nw;//ow原重、nw新的貨物重
public static int[][] node,cw;//記錄節點、目前重量
public static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
n=readnum();
m=readnum();
ow=new int[n];
nw=new int[m];
node=new int[n][2];
cw=new int[n][2];
for(int i=0;i<n;i++)ow[i]=readnum();
for(int i=0;i<m;i++)nw[i]=readnum();
int f;
for(int i=0;i<n-1;i++) {
f=readnum();
node[f][0]=readnum();//左子節點
node[f][1]=readnum();//右子節點
}
setup(1);
for(int i=0;i<m;i++) {
w=nw[i];
put(1);
}
bw.flush();
}
public static int readnum() throws IOException {//輸入
ret=0;
r=br.read();
while(r>47&&r<58) {
ret*=10;
r-=48;
ret+=r;
r=br.read();
}
return ret;
}
public static int setup(int x) {//前置作業
if(x>=n) {
return ow[x-n];
}
cw[x][0]=setup(node[x][0]);//左邊重
cw[x][1]=setup(node[x][1]);//右邊重
return cw[x][0]+cw[x][1];//總重
}
public static void put(int x) throws IOException {//放貨物
if(x>=n) {
bw.write(x+" ");//走到貨櫃輸出
return;
}
if(cw[x][0]<=cw[x][1]) {
cw[x][0]+=w;
put(node[x][0]);
}
else {
cw[x][1]+=w;
put(node[x][1]);
}
}
}
文章標籤
全站熱搜

https://zerojudge.tw/ShowThread?postid=24589&reply=0 這邊是我的失誤 寫完題目之後忘記自己IO的寫法...習慣性地打上了readLine().split(" ") 我自己的寫法這樣 final int n = readInt(), m = readInt(), n2 = n << 1; int[] parent = new int[n2], left = new int[n], right = new int[n], weight = new int[n2], w = new int[m]; 先建立一個weight陣列 用來儲存所有節點的重量 之後再將貨櫃的初始重量存進weight 接下來把貨物重量(w) 以及所有節點的關係(parent, left, right)都儲存起來 然後把所有葉節點(weight[n] ~ weight[(n << 1)-1])都跑一遍 從葉節點往上走訪,直到根節點 這一路上所有走訪到的節點的重量都需要加上該葉節點的重量 for(int i = n; i < n2; i++){ int j = parent[i]; while(parent[j] != 0){ weight[j] += weight[i]; j = parent[j]; } } 現在所有節點的重量都計算完畢 就可以開始將貨物放入 對於每個貨物 從根節點開始,比較左右節點的重量,直到走訪到葉節點 然後進行輸出 再從根節點開始往上走訪,更新重量 然後IO處理一下 時間就可以壓到1s內
是說 run time 因為 zj 主機的問題 所以會有所偏差(變慢) 我之前 AC (0.9s, 33.3MB) 的 code 現在變成 AC (1.5s, 33.5MB) 只能等之後更換主機才能改善
對於輸入的方式,我一開始使用readline的方式結果拿92%(其實我本來就習慣那種輸入方式),剩下四個測資有的MLE有的TLE,之後看到你在g310的留言,所以才改用你寫的那種比較特別的方式(可以省記憶體跟時間)結果有過,至於程式邏輯的部分是類似的,只有一開始的setup有區別,但其實也相差不遠,只是一個向上一個向下,不過我有點不懂為什麼在zj上你的記憶體用量比我少了一半(因為陣列大小與數量明明都開的差不多),啊至於運行時間的問題我之前也遇過,例如我暑假寫那題血緣關係我明明有AC,可是9月再丟一模一樣的程式上去卻TLE,所以系統可能真的有差,所以可能不要過於計較秒數比較好。
記憶體用量的問題 我不是很確定 但我覺得有可能是遞迴的關係 (遞迴所需的堆疊空間)
也是,你前面初始化節點的重量不是用遞迴,可能是這個原因所以記憶體用比較少