有線電視網【P1273】【樹形DP】
阿新 • • 發佈:2018-12-13
題目連結
一道樹形DP,但是它的想法還是可以稱之為樹形揹包,依舊是從大數往下推,我的這一道題中有對樹形揹包的完整講解,這裡呢,就是DP的列寫得怎麼樣列寫?dp[i][j],以i號節點為根節點時,取j個人的時候,需要的代價,我們希望最後的代價為“>=0”的。
完整程式碼:
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef long long ll; const int maxN=3005; int N, M; int dp[maxN][maxN], val[maxN]; struct eddge { int nex, val; eddge(int a=0, int b=0):nex(a), val(b) {} }; vector<eddge> vt[maxN]; int dfs(int u) { dp[u][0]=0; if(u>N-M) { dp[u][1]=val[u]; return 1; } int son=0, tmp=0, len=(int)vt[u].size(); for(int i=0; i<len; i++) { int v=vt[u][i].nex, cost=vt[u][i].val; son+=(tmp=dfs(v)); for(int j=son; j>=1; j--) { for(int k=1; k<=tmp; k++) { if(j>=k) dp[u][j]=max(dp[u][j], dp[u][j-k]+dp[v][k]-cost); } } } return son; } int main() { scanf("%d%d", &N, &M); for(int i=1; i<=(N-M); i++) { int e1, e2, e3; scanf("%d", &e1); while(e1--) { scanf("%d%d", &e2, &e3); vt[i].push_back(eddge(e2, e3)); } } for(int i=(N-M+1); i<=N; i++) scanf("%d", &val[i]); for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) dp[i][j]=-1000000; dfs(1); for(int i=M; i>=0; i--) { if(dp[1][i]>=0) { printf("%d\n", i); break; } else if(i==0) { printf("0\n"); break; } } return 0; }