寒假集训——Find Metal Mineral
2015-03-08 11:27
260 查看
题目链接
题意:给出一颗生成树,1<=N<=10000,在某一个节点有k个机器人(k<=10),然后机器人从这里开始走,要求遍历完节点,随便停到什么地方.求最少的路程总和.
题解: 树形dp,关键是dp[u][i],i的定义,因为机器人可能从子树再跑回来,然后为了避免重复讨论,应该定义为:在u为根的子树上停了几个机器人.这样定义肯定不会重复,重点就是之后的横着怎么dp过去.考虑最后一个,枚举它:如果是0,那么一定是只有一个机器人进来然后绕了一圈走了,可以反证.如果是1,一定是1个,反证可以,之后i个就是i..... 然后就能这样dp过去.定位也很关键,对于每一个子树的选择是:必须只能选一个的背包.
重点:树形dp中i的正确不重复定义,有效避免枚举,然后在这基础上正确推出dp方程.
题意:给出一颗生成树,1<=N<=10000,在某一个节点有k个机器人(k<=10),然后机器人从这里开始走,要求遍历完节点,随便停到什么地方.求最少的路程总和.
题解: 树形dp,关键是dp[u][i],i的定义,因为机器人可能从子树再跑回来,然后为了避免重复讨论,应该定义为:在u为根的子树上停了几个机器人.这样定义肯定不会重复,重点就是之后的横着怎么dp过去.考虑最后一个,枚举它:如果是0,那么一定是只有一个机器人进来然后绕了一圈走了,可以反证.如果是1,一定是1个,反证可以,之后i个就是i..... 然后就能这样dp过去.定位也很关键,对于每一个子树的选择是:必须只能选一个的背包.
重点:树形dp中i的正确不重复定义,有效避免枚举,然后在这基础上正确推出dp方程.
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <ctype.h> #include <limits.h> #include <cstdlib> #include <algorithm> #include <vector> #include <queue> #include <map> #include <stack> #include <set> #include <bitset> #define CLR(a) memset(a, 0, sizeof(a)) #define REP(i, a, b) for(int i = a;i < b;i++) #define REP_D(i, a, b) for(int i = a;i <= b;i++) typedef long long ll; using namespace std; const int maxn = 10000 + 100; int n, s, k, dp[maxn][20], vis[maxn]; struct info { int to, w; }; vector<info> G[maxn]; void dfs(int u) { vis[u] = 1;//树形dp for(int i = 0;i <= k;i++)//初始化,现在什么都没有,如果是叶子节点也是这样 { dp[u][i] = 0; } //dp[u][0] = 0; int tt = G[u].size(); //printf("---- %d\n", tt); for(int m = 0;m < tt;m++) { int to = G[u][m].to; int w = G[u][m].w; if(!vis[to])//开始子树 { dfs(to);//先弄掉子树 for(int i = k; i >= 0; i--)//倒着扫 { dp[u][i] += dp[to][0] + 2*w;//重点,因为一定要"选"这么多情况的一种,先随便用0来填充. for(int j = 1; j <= i; j++) { dp[u][i] = min(dp[u][i], dp[u][i - j] + j*w + dp[to][j]);//取小 } } } } // if(flag == 0) // { // for(int i = 0;i <= k;i++) // { // dp[u][i] = 0; // } // } } void solve() { CLR(dp); CLR(vis); dfs(s); printf("%d\n", dp[s][k]); } int main() { // freopen("13Min.txt", "r", stdin); //freopen("1out.txt", "w", stdout); while(scanf("%d%d%d", &n, &s, &k) != EOF) { REP_D(i, 1, n) { G[i].clear(); } REP_D(i, 1, n - 1) { int a, b, w; scanf("%d%d%d", &a, &b, &w); info tmp; tmp.to = b; tmp.w = w; G[a].push_back(tmp); tmp.to = a; G[b].push_back(tmp); } solve(); } return 0; }
相关文章推荐
- HDU 4003 Find Metal Mineral
- HDU 4003 Find Metal Mineral
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- hdu 4003 Find Metal Mineral 树形DP
- HDOJ 4003 Find Metal Mineral(树形DP)
- hdu 4003 Find Metal Mineral
- HDU 4003 Find Metal Mineral(树形dp + 分组背包)
- HDU 4003 Find Metal Mineral
- hdu 4003 Find Metal Mineral 树形dp+分组背包
- hdu 4003 Find Metal Mineral
- hdu 4003 Find Metal Mineral (树形背包dp)
- hdu 4003 Find Metal Mineral(树形DP)
- HDU 4003 Find Metal Mineral (树形DP,经典)
- hdu 4003 Find Metal Mineral
- HDU 4003 Find Metal Mineral 树形DP
- HDU-4003 Find Metal Mineral (树上背包)
- HDU 4003 Find Metal Mineral (树形DP+分组背包)
- HDU 4003 Find Metal Mineral 树上分组背包
- HDOJ题目4003 Find Metal Mineral(树状dp)
- HDU 4003 Find Metal Mineral(分组背包+树形DP)