http://poj.org/problem?id=2486
题意:
有n个点,每个点有一个权值,从1出发,走k步,最多能获得多少权值。(每个点只能获得一次)
思路:
从1点开始,往下dfs,对于每个结点,把时间分配给它的子节点,然后求一个最大值。
但是要注意的是,它有可能会走了之后然后又走回到父亲结点,这样的话,状态转移方程需要多考虑一下。
d【u】【j】【0/1】表示从u结点出发走 j 时所能获得的最大权值(0/1表示是否返回u结点)。
d[u][j][0]=max(d[u][j][0],d[u][j-t][0] + d[v][t-2][0]); d[u][j][1]=max(d[u][j][1],d[u][j-t][0] + d[v][t-1][1]); d[u][j][1]=max(d[u][j][1],d[u][j-t][1] + d[v][t-2][0]);
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn = 500+5; 17 18 int n, k; 19 20 int val[maxn]; 21 int vis[maxn]; 22 23 vector<int> g[maxn]; 24 25 int d[maxn][maxn][2]; 26 27 void dfs(int u) 28 { 29 vis[u]=1; 30 for(int i=0;i<g[u].size();i++) 31 { 32 int v=g[u][i]; 33 if(vis[v]) continue; 34 dfs(v); 35 for(int j=k;j>=1;j--) 36 { 37 for(int t=1;t<=j;t++) 38 { 39 d[u][j][0]=max(d[u][j][0],d[u][j-t][0]+d[v][t-2][0]); 40 d[u][j][1]=max(d[u][j][1],d[u][j-t][0]+d[v][t-1][1]); 41 d[u][j][1]=max(d[u][j][1],d[u][j-t][1]+d[v][t-2][0]); 42 } 43 } 44 } 45 } 46 47 int main() 48 { 49 //freopen("in.txt","r",stdin); 50 while(~scanf("%d%d",&n, &k)) 51 { 52 for(int i=1;i<=1000;i++) g[i].clear(); 53 memset(d,0,sizeof(d)); 54 55 for(int i=1;i<=n;i++) 56 { 57 scanf("%d",&val[i]); 58 for(int j=0;j<=k;j++) 59 d[i][j][0]=d[i][j][1]=val[i]; 60 } 61 62 for(int i=1;i<n;i++) 63 { 64 int u,v; 65 scanf("%d%d",&u,&v); 66 g[u].push_back(v); 67 g[v].push_back(u); 68 } 69 70 memset(vis,0,sizeof(vis)); 71 dfs(1); 72 printf("%d ",max(d[1][k][0],d[1][k][1])); 73 } 74 return 0; 75 }