zoukankan      html  css  js  c++  java
  • poj1639 Picnic Planning

    这题首先感慨下, 我的代码真的是太垃圾了。

    其实这题的思想是:堆+prime+dp, 来做的, 我看了下我的代码总是冗余很重, 所以直接去掉堆了。 

    这题的想法是限制的最小生成树。

    1.把所有的字母转化成图。

    2.去掉定点Park, 然后建最小生成树。 同时在每一个最小生成树连一条到定点的边(这条边到该树最短)。

    3.对每颗最小生成树进行dfs

    4.枚举定点的每一个边。选出差值最大的那条边然后修改最小生成树, 之后再从这点出发, dfs。

    View Code
    #include<stdio.h>
    #include<string.h>
    #define maxn 23
    #define inf 0x7ffffff
    
    int map[maxn][maxn], e[maxn][maxn], edge[maxn][maxn];
    int dist[maxn], visit[maxn];
    int sum_val;
    int n, m;
    char name[maxn][11];
    int flag[maxn], pre[maxn], last[maxn][maxn];
    int name_count;
    int edge_visit[maxn];
    int k_th;
    int flag_point;
    
    int find()
    {
        int i ;
        for (i = 0; i <= name_count; i ++)
        {
            if (strcmp(name[i], name[name_count + 1]) == 0)
            {
                return i;
            }
        }
        name_count ++;
        return i;
    }
    
    inline void add_map(int x, int y, int val)
    {
        map[x][22] ++; 
        map[x][map[x][22]] = y;
        map[y][22] ++;
        map[y][map[y][22]] = x;
        e[x][y] = e[y][x] = val;
    }
    
    void init()
    {
        int i, x, y, val;
        
        memset(map, 0, sizeof(map));
        memset(e, 0, sizeof(e));
        memset(last, 0, sizeof(last));
        name_count = 0;
        sum_val = 0;
        flag_point = 0;
        strcpy(name[0], "Park");
        for (i = 0; i < m; i++)
        {
            scanf("%s", name[name_count + 1]);
            x = find();
            scanf("%s", name[name_count + 1]);
            y = find();
            scanf("%d", &val);
            add_map(x, y, val);
        }
        scanf("%d", &k_th);
    
    }
    
    void add_edge(int x, int y)
    {
        edge[x][22] ++;
        edge[x][edge[x][22]] = y;
        edge[y][22] ++ ;
        edge[y][edge[y][22]] = x;
        
    }
    
    void check(int parent, int current)
    {
        for (int i = 1; i <= map[current][22]; i ++)
        {
            if (parent != map[current][i] && map[current][i] != 0 && edge_visit[map[current][i]] == 0)
            {
                add_edge(current, map[current][i]);
            }
        }
        for (int i = 1; i <= map[current][22]; i ++)
        {
            if (parent != map[current][i] && map[current][i] != 0 && edge_visit[map[current][i]] == 0 )
            {
                edge_visit[map[current][i]] = 1;
                check(current, map[current][i]);
            }
        }
    }
    
    inline void judge(int &min_point, int &min_val, int point)
    {
        if (e[point][0] > 0 && e[point][0] < min_val)
        {
            min_point = point;
            min_val = e[point][0];
        }
    }
    
    inline void add_last(int x, int y)
    {
        last[x][22] ++;
        last[x][last[x][22]] = y;
        last[y][22] ++;
        last[y][last[y][22]] = x;
    }
    
    void prime(int start)
    {
        int i, j, k, max_val, min_val;
        int min_point;
        min_val = inf;
    
        for (i = 1; i <= name_count; i ++)
        {
            dist[i] = inf;
            pre[i] = start;
        }
        for (i = 1; i <= edge[start][22]; i ++)
        {
            dist[edge[start][i]] = e[start][edge[start][i]];
        }
        dist[start] = inf;
        visit[start] = 1;
        judge(min_point, min_val, start);
    
        for (i = 2; i <= name_count; i ++)
        {
            max_val = inf;
            k = 0;
            for (j = 1; j <= name_count; j ++)
            {
                if (visit[j] == 0 && dist[j] < max_val)
                {
                    k = j;
                    max_val = dist[j];
                }
            }
            if (max_val == inf)
            {
                break;
            }
            judge(min_point, min_val, k);
            visit[k] = 1;
            add_last(pre[k], k);
            sum_val += max_val;
            for (j = 1; j <= edge[k][22]; j ++)
            {
                int x = edge[k][j];
                if (visit[x] == 0 && dist[x] > e[k][x] && x != 0)
                {
                    dist[x] = e[k][x];
                    pre[x] = k;
                }
            }
        }
        add_last(0, min_point);
        sum_val += e[0][min_point];
        flag[min_point] = 1;
        return;
    }
    
    struct node
    {
        int left, right, val;
    }dp[maxn][maxn];
    int dp_point;
    
    inline void add_dp(int left, int right, int val, int dp_right)
    {
        dp[dp_point][dp_right].left = left;
        dp[dp_point][dp_right].right = right;
        dp[dp_point][dp_right].val = val;
        dp[flag_point][dp_right].val = 0;
        //printf("%d %d\n", flag_point, dp_right);
    }
    
    void dfs(int parent, int current, int left, int right, int val)
    {
        //dp[flag_point][current].val = 0;
        for (int i = 1; i <= last[current][22]; i ++)
        {
            int x = last[current][i];
            if (x != parent)
            {
                if (val < e[x][current])
                {
                    add_dp(x, current, e[x][current], x);
                    dfs(current, x, current, x, e[x][current]);
                }
                else 
                {
                    add_dp(left, right, val, x);
                    dfs(current, x, left, right, val);
                }
            }
        }
    }
    
    void del(int left, int right)
    {
        int k = 1;
        while (last[left][k] != right) k ++;
        while (k < last[left][22]) last[left][k] = last[left][k + 1], k ++;
        k = 1;
        while (last[right][k] != left) k ++;
        while (k < last[right][22]) last[right][k] = last[right][k + 1], k ++;
        last[left][22]--;
        last[right][22] --;
    }
    
    void funs()
    {
        memset(visit, 0, sizeof(visit));
        memset(last, 0, sizeof(last));
        memset(&dp, 0, sizeof(dp));
    
        for (int i = 1; i <= name_count; i ++)
        {
            if (visit[i] == 0)
            {
                memset(edge, 0, sizeof(edge));
                memset(edge_visit, 0, sizeof(edge_visit));
                edge_visit[i] = 1;
                check(0, i);
                prime(i);
            }
        }
        
        int count = 0;
        for (int i = 1; i <= last[0][22]; i ++)
        {
            dp_point = last[0][i];
            dfs(0, last[0][i], 0, 0, 0);
            count ++;
        }
        
        for (int i = count + 1; i <= k_th && i <= map[0][22]; i ++)
        {
            int count_val, count_left, count_right;
            int count_point;
            count_val = 0;
            for (int j = 1; j <= map[0][22]; j ++)
            {
                if (flag[map[0][j]] == 0)
                {
                    for (int k = 1; k <= last[0][22]; k ++)
                    {
                        int val = dp[last[0][k]][map[0][j]].val;
                        if (val > 0 && val - e[0][map[0][j]] > count_val )
                        {
                            count_val = val - e[0][map[0][j]];
                            count_left = dp[last[0][k]][map[0][j]].left;
                            count_right = dp[last[0][k]][map[0][j]].right;
                            count_point = map[0][j];
                            flag_point = last[0][k];
                        }
                    }
                }
            }
            //printf("%d %d %d %d \n", count_left, count_right, count_point, count_val);
            if (count_val == 0)
            {
                break;
            }
            sum_val -= count_val;
            del(count_left, count_right);
            add_last(0, count_point);
            flag[count_point] = 1;
            dp_point = count_point;
            dfs(0, count_point, 0, 0, 0);
        }
        
        printf("Total miles driven: %d\n", sum_val);
        return;
    }
    
    int main()
    {
        while (scanf("%d", &m) != EOF)
        {
            init();
            funs();
        }
        return 0;
    }
  • 相关阅读:
    Myeclipse学习总结(5)——Myeclipse常用快捷键再学习
    Myeclipse学习总结(5)——Myeclipse常用快捷键再学习
    Java基础学习总结(37)——Java23中设计模式(Design Patterns)详解
    Java基础学习总结(37)——Java23中设计模式(Design Patterns)详解
    Java基础学习总结(37)——Java23中设计模式(Design Patterns)详解
    Git学习总结(4)——我的Git忽略文件
    Git学习总结(4)——我的Git忽略文件
    Git学习总结(4)——我的Git忽略文件
    《跟唐老师学习云网络》 -第5篇 Ping喂报文
    深入比特币原理(五)——高级交易与脚本
  • 原文地址:https://www.cnblogs.com/cxiaoln/p/2439098.html
Copyright © 2011-2022 走看看