日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[蓝桥杯]算法提高 金属采集(树形dp)

發布時間:2023/12/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [蓝桥杯]算法提高 金属采集(树形dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題描述
人類在火星上發現了一種新的金屬!這些金屬分布在一些奇怪的地方,不妨叫它節點好了。一些節點之間有道路相連,所有的節點和道路形成了一棵樹。一共有 n 個節點,這些節點被編號為 1~n 。人類將 k 個機器人送上了火星,目的是采集這些金屬。這些機器人都被送到了一個指定的著落點, S 號節點。每個機器人在著落之后,必須沿著道路行走。當機器人到達一個節點時,它會采集這個節點蘊藏的所有金屬礦。當機器人完成自己的任務之后,可以從任意一個節點返回地球。當然,回到地球的機器人就無法再到火星去了。我們已經提前測量出了每條道路的信息,包括它的兩個端點 x 和 y,以及通過這條道路需要花費的能量 w 。我們想花費盡量少的能量采集所有節點的金屬,這個任務就交給你了。

輸入格式
第一行包含三個整數 n, S 和 k ,分別代表節點個數、著落點編號,和機器人個數。

接下來一共 n-1 行,每行描述一條道路。一行含有三個整數 x, y 和 w ,代表在 x 號節點和 y 號節點之間有一條道路,通過需要花費 w 個單位的能量。所有道路都可以雙向通行。

輸出格式
輸出一個整數,代表采集所有節點的金屬所需要的最少能量。
樣例輸入
6 1 3
1 2 1
2 3 1
2 4 1000
2 5 1000
1 6 1000
樣例輸出
3004
樣例說明
所有機器人在 1 號節點著陸。
第一個機器人的行走路徑為 1->6 ,在 6 號節點返回地球,花費能量為1000。
第二個機器人的行走路徑為 1->2->3->2->4 ,在 4 號節點返回地球,花費能量為1003。
第一個機器人的行走路徑為 1->2->5 ,在 5 號節點返回地球,花費能量為1001。
數據規模與約定
本題有10個測試點。
對于測試點 1~2 , n <= 10 , k <= 5 。
對于測試點 3 , n <= 100000 , k = 1 。
對于測試點 4 , n <= 1000 , k = 2 。
對于測試點 5~6 , n <= 1000 , k <= 10 。
對于測試點 7~10 , n <= 100000 , k <= 10 。
道路的能量 w 均為不超過 1000 的正整數。

思路:挺經典的一道樹形dp的題目。
dp[i][j]代表著以i為根的子樹,利用j個機器人去收集這個子樹的金屬,收集完了就返回地球所需要的最小花費,那么最終輸出dp[n][k]。
狀態轉移方程就是:dp[i][r]=min(dp[i][r],dp[i][r-j]+dp[to][j]+j*w).假設以i為根的子樹中分配了r個機器人,那么我們分配了j個到以to為根的子樹中,那么i-to的這一條邊就需要有j個機器人走,因為不需要返回,所以只需要乘一次。
但是有一種情況例外,就是分配給以to為根的子樹的機器人中,沒有一個返回了地球,這種情況我們可以考慮一下,以to為根的子樹節點中的金屬都被收集了,但是所以的機器人又返回了,我們貪心的去想,收集的金屬數目是不會隨著機器人的數目變的,如果機器人數目多的話,代價反而大,因為i-to這一條邊走的機器人多了,這種情況下,最優的就是派一個機器人下去收集,然后再返回,這樣是最優的。
代碼如下:

#include<bits/stdc++.h> #define ll long long using namespace std;const int maxx=1e5+100; struct edge{int to,next,w; }e[maxx<<1]; int dp[maxx][15],head[maxx<<1]; int n,s,k,tot;inline void init() {memset(head,-1,sizeof(head));memset(dp,0,sizeof(dp));tot=0; } inline void add(int u,int v,int w) {e[tot].next=head[u],e[tot].to=v,e[tot].w=w,head[u]=tot++; } inline void dfs(int u,int f) {for(int i=head[u];i!=-1;i=e[i].next){int to=e[i].to;if(to==f) continue;dfs(to,u);for(int r=k;r>=0;r--){//如果順序的話,前面結果改變會影響后面的情況。dp[u][r]+=dp[to][0]+2*e[i].w;//特殊情況for(int j=1;j<=r;j++) dp[u][r]=min(dp[u][r],dp[u][r-j]+dp[to][j]+j*e[i].w);}} } int main() {scanf("%d%d%d",&n,&s,&k);init();int x,y,z;for(int i=1;i<n;i++){scanf("%d%d%d",&x,&y,&z);add(x,y,z);add(y,x,z);}dfs(s,0);printf("%d\n",dp[s][k]);return 0; }

努力加油a啊,(o)/~

總結

以上是生活随笔為你收集整理的[蓝桥杯]算法提高 金属采集(树形dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。