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]);
        }
    }
    

      

  • 相关阅读:
    python os.path.dirname()
    python os.path.basename()方法
    python mmap对象
    python 读取二进制数据到可变缓冲区中
    sklearn常见分类器的效果比较
    用matplotlib获取雅虎股票数据并作图
    使用 lxml 中的 xpath 高效提取文本与标签属性值
    如何用 Python 爬取需要登录的网站
    python 线程及线程池
    使用Python代码处理Excel
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2177896.html
Copyright © 2011-2022 走看看