hdu 4003(树形dp)

来源:互联网 发布:linux多线程编程 书籍 编辑:程序博客网 时间:2024/06/06 19:01

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003

思路:dp[i][j]表示以i为根选择j个机器人的最小花费,然后就是背包了:dp[u][i]=min(dp[u][i],dp[u][i-j]+dp[v][j]+j*w)(1<<j<<i,u是v的根)。值得注意的是dp[u][0]的意义,dp[i][0]表示以i为根的子树派一个机器人遍历完整棵子树后又回到i的花费。

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define MAXN 10100 8 #define inf 1<<30 9 10 struct Edge{11     int v,w;12     Edge(int vv,int ww):v(vv),w(ww){}13 };14 15 int n,s,k;16 int dp[MAXN][20];17 vector<vector<Edge> >G;18 19 void dfs(int u,int father)20 {21     for(int i=0;i<G[u].size();i++){22         int v=G[u][i].v,w=G[u][i].w;23         if(v==father)continue;24         dfs(v,u);25         for(int i=k;i>=0;i--){26             dp[u][i]+=dp[v][0]+2*w;//v所在子树不放置机器人,那么必然要派一个机器人从u到v去遍历v所在子树并且回到u.27             for(int j=1;j<=i;j++){ //子树放置1-j个机器人28                 dp[u][i]=min(dp[u][i],dp[u][i-j]+dp[v][j]+j*w);29             }30         }31     }32 }33 34 int main()35 {36     int u,v,w;37     while(~scanf("%d%d%d",&n,&s,&k)){38         G.clear();39         G.resize(n+2);40         for(int i=1;i<n;i++){41             scanf("%d%d%d",&u,&v,&w);42             G[u].push_back(Edge(v,w));43             G[v].push_back(Edge(u,w));44         }45         memset(dp,0,sizeof(dp));46         dfs(s,-1);47         printf("%d\n",dp[s][k]);48     }49     return 0;50 }
View Code

 

 

0 0
原创粉丝点击