zoukankan      html  css  js  c++  java
  • HDU4003 Find Metal Mineral

    HDU4003 Find Metal Mineral

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)

    Total Submission(s): 759    Accepted Submission(s): 298

    Problem Description

    Humans have discovered a kind of new metal mineral on Mars which are distributed in point‐like with paths connecting each of them which formed a tree. Now Humans launches k robots on Mars to collect them, and due to the unknown reasons, the landing site S of all robots is identified in advanced, in other word, all robot should start their job at point S. Each robot can return to Earth anywhere, and of course they cannot go back to Mars. We have research the information of all paths on Mars, including its two endpoints x, y and energy cost w. To reduce the total energy cost, we should make a optimal plan which cost minimal energy cost.

    Input

    There are multiple cases in the input. 

    In each case: 

    The first line specifies three integers N, S, K specifying the numbers of metal mineral, landing site and the number of robots. 

    The next n‐1 lines will give three integers x, y, w in each line specifying there is a path connected point x and y which should cost w. 

    1<=N<=10000, 1<=S<=N, 1<=k<=10, 1<=x, y<=N, 1<=w<=10000.

    Output

    For each cases output one line with the minimal energy cost.

    Sample Input

    3 1 1

    1 2 1

    1 3 1

    3 1 2

    1 2 1

    1 3 1

    Sample Output

    3

    2

    Hint

    In the first case: 1->2->1->3 the cost is 3;

    In the second case: 1->2; 1->3 the cost is 2;

    ************************************************************************************

    这个是2011大连赛区网络赛的第三道。

    题目大意:给定k个机器人去遍历n个节点的树,求最小花费

    一开始不会,看了大牛的才懂。实在惭愧,看得太认真了,结果自己写程序就长得和大牛程序几乎一样了。

    一道很好的树形dp

    dp[pos][num]表示以pos为根节点的子树下,用去num个机器人,所得到的最小值

    特别的是当num==0的时候,dp[pos][0]表示用一个机器人去走完所有子树,最后又回到pos这个节点

    状态转移:dp[pos][num]=min∑{dp[pos_j][num_j]+w_j},pos_j是pos的所有儿子,

    当num_j==0的时候,和别的时候不同,特别处理一下就好。

    状态转移并不难,最精华的,我不认为是状态转移,而是转移时使用的那个“分组背包”思想。

    使用一维数组的“分组背包”伪代码如下:

    for 所有的组i

        for v=V..0

            for 所有的k属于组i

                f[v]=max{f[v],f[v-c[k]]+w[k]}

    上面那个状态转移时,要把num个机器人分给所有它的儿子,状态太多了,不好做,用“分组背包”实在太帅了。
    #include <stdio.h>
    #include <string.h>
    #define INF 0x3f3f3f3f
    #define MIN(a,b) ((a)<(b)?(a):(b))
    
    int id,head[10001];
    int n,s,k;
    int dp[10001][11];
    
    struct Edge
    {
        int ed,val,nxt;
    }edge[20001];
    
    void add_edge(int sta,int ed,int val)
    {
        edge[id].ed=ed;
        edge[id].val=val;
        edge[id].nxt=head[sta];
        head[sta]=id++;
    }
    
    void dpt(int pos,int pre)
    {
        int mark=0;
        for(int i=head[pos];~i;i=edge[i].nxt)
            if(edge[i].ed!=pre)
                dpt(edge[i].ed,pos),mark=1;
        if(mark==0)return ;
        /*这以下就是用“分组背包”的状态转移,
        3个for就对应了“分组背包”的那3个循环*/
        for(int i=head[pos];~i;i=edge[i].nxt)
        {
            int t=edge[i].ed;
            if(t==pre)continue;
            for(int j=k;j>=0;j--)
            {
                if(j==0)dp[pos][0]+=dp[t][0]+2*edge[i].val;
                else
                {
                    dp[pos][j]+=dp[t][0]+2*edge[i].val;
                    for(int u=1;u<=j;u++)
                        dp[pos][j]=MIN(dp[pos][j],dp[pos][j-u]+dp[t][u]+u*edge[i].val);
                }
            }
        }
    }
    
    int main()
    {
        while(scanf("%d%d%d",&n,&s,&k)==3)
        {
            memset(head,-1,sizeof(head));
            memset(edge,0,sizeof(edge));
            memset(dp,0,sizeof(dp));
            id=0;
            for(int i=1;i<n;i++)
            {
                int sta,ed,val;
                scanf("%d%d%d",&sta,&ed,&val);
                add_edge(sta,ed,val);
                add_edge(ed,sta,val);
            }
            dpt(s,0);
            printf("%d\n",dp[s][k]);
        }
    }
    

      

  • 相关阅读:
    导入测试用例的设计
    质量管理的精髓
    ios crash的原因与抓取crash日志的方法
    怎样实现excel隔行隔列变色效果的方法
    如何提高员工的质量意识?
    史上最全的测试团队组建方法
    如何写好缺陷报告?
    你还不知道?这四个因素决定了你的养老金待遇!
    各手机截屏方法收集
    利用drozer进行Android渗透测试
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2177896.html
Copyright © 2011-2022 走看看