RQNOJ 188 購物問題:樹形dp
阿新 • • 發佈:2017-09-01
cin href ++ problem expr ive 子節點 col sco
題目鏈接:https://www.rqnoj.cn/problem/188
題意:
商場以超低價格出售n個商品,購買第i個商品所節省的金額為w[i]。
為了防止虧本,有m對商品是不能同時買的。但保證商品關系不出現環,不會出現如:(1,2) , (2,4) , (1,4)。
問你最多能節省的金額。
題解:
簡直和POJ 2342 Anniversary party像極了(*/ω\*)
將不能同時買的商品間連一條無向邊。
所以子節點和父節點不能同時選。
唯一不同的是POJ是一棵樹,而這道題是一片森林。需要對於每一棵樹分別求dp,然後求和。
表示狀態:
dp[i][j] = max discount
i:考慮到第i個商品(節點i)
j:是否選節點i (j == 0 / 1)
找到答案:
ans = ∑ max(dp[root[i]][0],dp[root[i]][1]) (root[i]為每棵樹的根)
如何轉移:
dp[i][1] = sigma dp[son][0] (選父節點)
dp[i][0] = sigma max dp[son][0/1] (不選父節點)
在dfs中:
dp[now][1] = w[i]
dfs(nex...)
dp[par][1] += dp[now][0]
dp[par][0] += max(dp[now][0], dp[now][1])
邊界條件:
dp[i][1] = w[i] (至少選自己)
dp[i][0] = 0
AC Code:
1 // state expression: 2 // dp[i][j] = max discount 3 // i: considering ver i 4 // j: whether to select j ver 5 // 6 // find the answer: 7 // max dp[root][0/1] 8 // 9 // transferring: 10 // dp[i][1] = sigma dp[son][0] 11 // dp[i][0] = sigma max dp[son][0/1]12 // dfs: 13 // dp[now][1] = w[i] 14 // dfs(nex...) 15 // dp[par[now]][1] += dp[now][0] 16 // dp[par[now]][0] += max(dp[now][0], dp[now][1]) 17 // 18 // boundary: 19 // dp[i][1] = w[i] 20 // dp[i][0] = 0 21 #include <iostream> 22 #include <stdio.h> 23 #include <string.h> 24 #include <vector> 25 #define MAX_N 1005 26 27 using namespace std; 28 29 int n,m; 30 int a,b; 31 int ans; 32 int w[MAX_N]; 33 int dp[MAX_N][2]; 34 bool vis[MAX_N]; 35 vector<int> edge[MAX_N]; 36 37 void read() 38 { 39 cin>>n>>m; 40 for(int i=1;i<=n;i++) 41 { 42 cin>>w[i]; 43 } 44 for(int i=0;i<m;i++) 45 { 46 cin>>a>>b; 47 edge[a].push_back(b); 48 edge[b].push_back(a); 49 } 50 } 51 52 void dfs(int now,int par) 53 { 54 vis[now]=true; 55 dp[now][1]=w[now]; 56 for(int i=0;i<edge[now].size();i++) 57 { 58 int temp=edge[now][i]; 59 if(temp!=par) dfs(temp,now); 60 } 61 if(par!=-1) 62 { 63 dp[par][1]+=dp[now][0]; 64 dp[par][0]+=max(dp[now][0],dp[now][1]); 65 } 66 } 67 68 void solve() 69 { 70 memset(dp,0,sizeof(dp)); 71 memset(vis,false,sizeof(vis)); 72 ans=0; 73 for(int i=1;i<=n;i++) 74 { 75 if(!vis[i]) 76 { 77 dfs(i,-1); 78 ans+=max(dp[i][0],dp[i][1]); 79 } 80 } 81 } 82 83 void print() 84 { 85 cout<<ans<<endl; 86 } 87 88 int main() 89 { 90 read(); 91 solve(); 92 print(); 93 }
RQNOJ 188 購物問題:樹形dp