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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp

發布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

給你一棵 $n$ 層的完全二叉樹,每個節點可以染黑白兩種顏色。對于每個葉子節點及其某個祖先節點,如果它們均為黑色則有一個貢獻值,如果均為白色則有另一個貢獻值。要求黑色的葉子節點數目不超過 $m$ ,求最大總貢獻值。

$n\le 10$

輸入

第一行兩個數 n;m。接下來 2^(n-1) 行,每行n-1 個數,第 i 行表示編號為 2^(n-1)-1+ i 的平民對其n-1直系上司的作戰貢獻度,其中第一個數表示對第一級直系上司,即編號為 (2^(n-1)-1+ i)/2 的貴族的作戰貢獻度 wij,依次往上。接下來 2^(n-1)行,每行n-1個數,第i行表示編號為 2^(n-1)-1+ i的平民對其n-1個直系上司的后勤貢獻度,其中第一個數表示對第一級直系上司,即編號為 (2^(n-1)-1+ i)/2 的貴族的后勤貢獻度 fij ,依次往上。

輸出

一行一個數表示滿足條件的最大貢獻值

樣例輸入

3 4
503 1082
1271 369
303 1135
749 1289
100 54
837 826
947 699
216 389

樣例輸出

6701


題解

暴力+樹形背包dp

[NOI2006]網絡收費 的套路。

提前計算葉子節點的總貢獻,設 $f[i][j]$ 表示以 $i$ 為根的子樹中,$j$ 個葉子節點的顏色為黑色( $j$ 個平民選擇戰爭)的最大總貢獻值。

那么這顯然是一個樹形背包問題,處理左右節點后背包合并即可。

但是由于葉子節點的貢獻與其祖先節點的顏色選擇有關,我們不能直接得到貢獻。由于這是一棵完全二叉樹,因此可以暴力枚舉每個非葉子節點的顏色。

這樣有遞歸式 $T(1)=O(\log k),T(k)=4T(\frac k2)+O(k^2)$ ,不考慮 $T(1)$ 時根據主定理解得 $T(k)=O(k^2\log k)$ ,考慮 $T(1)$ 時 $T(1)$ 被計算了 $k^2$ 次,貢獻為 $O(k^2\log k)$ 。

因此總的時間復雜度是正確的,為 $O(2^{2n}·n)$ 。

#include <cstdio> #include <algorithm> #define N 1030 using namespace std; int n , w[N][12] , v[N][12] , f[N][N] , p[12]; void dfs(int x , int d) {int i , j;for(i = 0 ; i <= 1 << d ; i ++ ) f[x][i] = 0;if(!d){for(i = 1 ; i <= n ; i ++ ){if(p[i]) f[x][1] += w[x][i];else f[x][0] += v[x][i];}return;}p[d] = 0 , dfs(x << 1 , d - 1) , dfs(x << 1 | 1 , d - 1);for(i = 0 ; i <= 1 << (d - 1) ; i ++ )for(j = 0 ; j <= 1 << (d - 1) ; j ++ )f[x][i + j] = max(f[x][i + j] , f[x << 1][i] + f[x << 1 | 1][j]);p[d] = 1 , dfs(x << 1 , d - 1) , dfs(x << 1 | 1 , d - 1);for(i = 0 ; i <= 1 << (d - 1) ; i ++ )for(j = 0 ; j <= 1 << (d - 1) ; j ++ )f[x][i + j] = max(f[x][i + j] , f[x << 1][i] + f[x << 1 | 1][j]); } int main() {int m , i , j , ans = 0;scanf("%d%d" , &n , &m) , n -- ;for(i = 0 ; i < (1 << n) ; i ++ ) for(j = 1 ; j <= n ; j ++ ) scanf("%d" , &w[i + (1 << n)][j]);for(i = 0 ; i < (1 << n) ; i ++ ) for(j = 1 ; j <= n ; j ++ ) scanf("%d" , &v[i + (1 << n)][j]);dfs(1 , n);for(i = 0 ; i <= m ; i ++ ) ans = max(ans , f[1][i]);printf("%d\n" , ans);return 0; }

?

轉載于:https://www.cnblogs.com/GXZlegend/p/8300883.html

總結

以上是生活随笔為你收集整理的【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp的全部內容,希望文章能夠幫你解決所遇到的問題。

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