# APCS 2021/01 不負責程式碼範例 ## 1. 購買力 ### [題目敘述](https://zerojudge.tw/ShowProblem?problemid=f605) ```cpp= //#include <bits/stdc++.h> #include <iostream> #include <math.h> using namespace std; int main(){ int n, d, a[3]; cin >> n >> d; int cnt = 0, sum = 0; for(int i = 0; i < n; i++){ cin >> a[0] >> a[1] >> a[2]; sort(a, a+3); if(a[2] - a[0] >= d){ cnt++; sum += (a[0] + a[1] + a[2])/3; } } cout << cnt << " " << sum << endl; return 0; } ``` ## 2. 流量 ### [題目敘述](https://zerojudge.tw/ShowProblem?problemid=f606) ```cpp= //#include <bits/stdc++.h> #include <iostream> using namespace std; #define N 51 // server to city: mxn array int Q[N][N]; // city flow: mxm array int f[N][N] = {{0}}; int c[N]; int main(){ int n, m, k; cin >> n >> m >> k; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ cin >> Q[i][j]; } } int min, cost; for(int x = 0; x < k; x++){ // reset city flow array for(int i = 0; i < m; i++){ for(int j = 0; j < m; j++){ f[i][j] = 0; } } // count city flow according to specific cases cost = 0; for(int i = 0; i < n; i++){ cin >> c[i]; for(int j = 0; j < m; j++){ f[c[i]][j] += Q[i][j]; } } // count cost for(int i = 0; i < m; i++){ for(int j = 0; j < m; j++){ if(i == j) cost += f[i][j]; else if (f[i][j] <= 1000) cost += 3*f[i][j]; else cost += 3000 + 2*(f[i][j]-1000); } } if (x == 0 || cost < min) min = cost; } cout << min << endl; } ``` ## 3. 切割費用 ### [題目敘述](https://zerojudge.tw/ShowProblem?problemid=f607) ![](https://i.imgur.com/jB4uoRO.png) :::spoiler 【會TLE的解法】依切割順序排序,遞迴解 ``` cpp= #include <bits/stdc++.h> using namespace std; #define N 200002 typedef long long LL; struct Cut{ int x; int i; }; bool icmp(Cut a, Cut b){ return a.i < b.i; } Cut a[N]; LL cost(Cut a[], int i, int p, int q, int n){ if (i == n-1){ if(a[i].x > p && a[i].x < q){ return q-p; } else { return 0; } } else if (a[i].x > p && a[i].x < q){ return q - p + cost(a, i+1, p, a[i].x, n) + cost(a, i+1, a[i].x, q, n); } else { return cost(a, i+1, p, q, n); } } int main(){ int n, L; cin >> n >> L; for(int j = 0; j < n; j++){ cin >> a[j].x >> a[j].i; } sort(a, a+n, icmp); cout << cost(a, 0, 0, L, n) << endl; return 0; } ``` ::: :::spoiler 【可以過但很慢的解法】依切割位置排序,左右分別找出最近的較小切割點 ``` cpp = #include <bits/stdc++.h> using namespace std; #define N 200002 typedef long long LL; struct Cut{ int x; int i; }; bool xcmp(Cut a, Cut b){ return a.x < b.x; } Cut a[N], b[N]; int main(){ int n, L; cin >> n >> L; for(int j = 0; j < n; j++){ cin >> a[j].x >> a[j].i; } for(int j = 0; j < n; j++){ b[j].x = a[j].x; b[j].i = a[j].i; } sort(a, a+n, icmp); sort(b, b+n, xcmp); LL sum = 0; for(int j = 0; j < n; j++){ int p = 0; int q = L; for(int k = j-1; k >= 0; k--){ if(b[k].i < b[j].i){ p = b[k].x; break; } } for(int k = j+1; k < n; k++){ if(b[k].i < b[j].i){ q = b[k].x; break; } } sum += q-p; //cout << "Point " << j << ", add " << q-p << endl; } cout << sum << endl; return 0; } ``` ::: ### [幾種解法參考](https://www.facebook.com/groups/359446638362710/permalink/502745984032774) ![](https://i.imgur.com/RmjpLbV.png) :::spoiler 【Sol 1 範例解法】先備知識:STL stack ``` cpp= #include <bits/stdc++.h> using namespace std; #define N 200002 typedef long long LL; struct Cut{ int x; int i; }; bool xcmp(Cut a, Cut b){ return a.x < b.x; } stack<Cut> S; Cut a[N]; int main(){ int n, L; cin >> n >> L; for(int j = 0; j < n; j++){ cin >> a[j].x >> a[j].i; } sort(a, a+n, xcmp); LL sum = 0; Cut h = {0, 0}; Cut t = {L, 0}; S.push(h); for(int i = 0; i < n; i++){ while(a[i].i < S.top().i){ S.pop(); } sum += a[i].x - S.top().x; S.push(a[i]); } while(!S.empty()){ S.pop(); } S.push(t); for(int i = n-1; i >= 0; i--){ while(a[i].i < S.top().i){ S.pop(); } sum += S.top().x - a[i].x; S.push(a[i]); } cout << sum << endl; return 0; } ``` ::: :::spoiler 【Sol 2 範例解法】先備知識:STL set、iterator 請參考[YUI HUANG的演算法筆記](https://yuihuang.com/zj-f607/) :::