1. 程式人生 > 其它 >2021寒假程式設計訓練----2021/01/02

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

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;
}