2021寒假程式設計訓練----2021/01/02
醫院設定
題目描述
設有一顆二叉樹如圖:
其中,圈中的數字表示結點中居民的人口。圈邊上數字表示結點編號,現在要求在某個結點上建立一個醫院,使所有居民所走的路程之和為最小,同時約定,相鄰接點之間的距離為 1。如上圖中,若醫院建在1 處,則距離和 =
4
+
12
+
2
×
20
+
2
×
20
=
136
4+12+2 \times 20+2\times20=136
4+12+2×20+2×20=136;若醫院建在 3 處,則距離和 =
4
×
2
+
13
+
20
+
40
=
81
4×2+13+20+40=81
輸入格式
第一行一個整數 n n n,表示樹的結點數。
接下來的 n n n行每行描述了一個結點的狀況,包含三個整數 w , u , v w, u, v w,u,v,其中 w w w 為居民人口數, u u u為左連結(為 0 0 0 表示無連結), v v v 為右連結(為 0 0 0 表示無連結)。
輸出格式
一個整數,表示最小距離和。
輸入樣例
5
13 2 3
4 0 0
12 4 5
20 0 0
40 0 0
輸出樣例
81
思路
對每個點做一次BFS即可,記得每次都要初始化d陣列,求最小值即可
#include <bits/stdc++.h>
using namespace std;
const int N = 110,M = N*2;
int n;
int h[N],idx,w[N];
queue<int>q;
int d[N];
struct Edge {
int next,to;
}edge[M];
void add(int a,int b) {
edge[idx].to = b;
edge[idx].next = h[a];
h[a] = idx++;
}
int bfs(int x) {
memset(d,0,sizeof d);
int ans = 0;
q. push(x);
while(q.size()) {
int t = q.front();
q.pop();
for (int i = h[t]; ~i; i = edge[i].next) {
int j = edge[i].to;
if(d[j]||j==x) continue;
d[j] = d[t]+1;
//cout<<"編號為:"<<j<<endl;
ans += d[j]*w[j];
q.push(j);
}
}
return ans;
}
int main() {
memset(h,-1,sizeof h);
cin >> n;
for (int i = 1; i <= n; i ++) {
int l,r;
cin >> w[i] >> l >> r;
if(l) add(i,l),add(l,i);
if(r) add(i,r),add(r,i);
}
int res = 0x3f3f3f3f;
for (int i = 1; i <= n; i ++) {
res = min(res,bfs(i));
}
cout << res << endl;
return 0;
}
膜拜
題目描述
神牛有很多…當然…每個同學都有自己衷心膜拜的神牛.
某學校有兩位神牛,神牛甲和神牛乙。新入學的 n n n 位同學們早已耳聞他們的神話。
所以,已經衷心地膜拜其中一位了。現在,老師要給他們分機房。但是,要麼保證整個機房都是同一位神牛的膜拜者,或者兩個神牛的膜拜者人數差不超過 m m m。另外,現在 n n n 位同學排成一排,老師只會把連續一段的同學分進一個機房。老師想知道,至少需要多少個機房。
輸入格式
輸入檔案第一行包含兩個整數 n n n 和 m m m。
第 2 2 2 到第 ( n + 1 ) (n + 1) (n+1) 行,每行一個非 1 1 1 即 2 2 2 的整數,第 ( i + 1 ) (i + 1) (i+1) 行的整數表示第 i i i 個同學崇拜的物件, 1 1 1 表示甲, 2 2 2 表示乙。
輸出格式
輸出一個整數,表示最小需要機房的數量。
輸入樣例
5 1
2
2
1
2
2
輸出樣例
2
思路
把2看成-1,題目就可以變成將序列最少分為多少段,使每段和的絕對值 ≤ m ≤m ≤m,求和可以用字首和,然後就是線性DP了。
時間複雜度 O ( n 2 ) O(n^2) O(n2)。
#include <bits/stdc++.h>
using namespace std;
const int N = 2510;
int dp[N],sum[N];
int main() {
int n,m;
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
int x;
cin >> x;
if(x == 1) sum[i] = sum[i-1]+1;
else sum[i] = sum[i-1]-1;
}
memset(dp+1,0x3f,sizeof dp);
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= i; j ++) {
if(abs(sum[i]-sum[j-1])==i-j+1||abs(sum[i]-sum[j-1])<=m)
dp[i] = min(dp[i],dp[j-1]+1);
}
}
cout << dp[n] << endl;
return 0;
}