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;
}
posted @ 2012-04-09 16:03  CY_K_YC  阅读(164)  评论(0编辑  收藏  举报