• bzoj3714 [PA2014]Kuglarz


                                                                                                                         3714: [PA2014]Kuglarz

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 805  Solved: 447
    [Submit][Status][Discuss]

    Description

    魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品。花费c_ij元,魔术师就会告诉你杯子i,i+1,…,j底下藏有球的总数的奇偶性。
    采取最优的询问策略,你至少需要花费多少元,才能保证猜出哪些杯子底下藏着球?

    Input

    第一行一个整数n(1<=n<=2000)。
    第i+1行(1<=i<=n)有n+1-i个整数,表示每一种询问所需的花费。其中c_ij(对区间[i,j]进行询问的费用,1<=i<=j<=n,1<=c_ij<=10^9)为第i+1行第j+1-i个数。

    Output

    输出一个整数,表示最少花费。

    Sample Input

    5
    1 2 3 4 5
    4 3 2 1
    3 4 5
    2 1
    5

    Sample Output

    7

    分析:我们要知道1到n个杯子中是否小球,必须要知道1~1,1~2...1~n个杯子中小球个数的奇偶性,事实上,对于每一次区间询问,我们知道了[l,r]的小球个数的奇偶性,也就是相当于从l-1转移到了r,也就是说如果我们知道了1~l-1的奇偶性,就能知道1~r的奇偶性,那么同样的反过来也是一样。我们从l-1到r连一条无向边,因为我们要知道1~1,1~2...1~n个杯子中小球个数的奇偶性,也就是这n个点被连通,我们只需要做一次最小生成树就好了.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int n,cnt,fa[2010];
    long long ans;
    
    struct node
    {
        int x, y, w;
    }e[2005000];
    
    bool cmp(node a, node b)
    {
        return a.w < b.w;
    }
    
    int find(int x)
    {
        if (x == fa[x])
            return x;
        return fa[x] = find(fa[x]);
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            for (int j = i; j <= n; j++)
            {
            int t;
            scanf("%d", &t);
            e[++cnt].x = i - 1;
            e[cnt].y = j;
            e[cnt].w = t;
            }
        sort(e + 1, e + cnt + 1, cmp);
        for (int i = 1; i <= n; i++)
            fa[i] = i;
        for (int i = 1; i <= cnt; i++)
        {
            int fx = find(e[i].x), fy = find(e[i].y);
            if (fx != fy)
            {
                ans += e[i].w;
                fa[fx] = fy;
            }
        }
        printf("%lld
    ", ans);
    
    return 0; }
  • 相关阅读:
    C 找到该列最大的前两个数字
    C 寻找和最大的子序列
    C 找出最长的回文子串(不区分大小写)
    C 字符串数组
    C 寻找重复字符并输出他们的位置
    C 寻找0~100的守形数
    C 在外部函数中修改指针变量
    C int转为二进制 再进行与操作
    C 计算阶乘之和
    C 奇偶校验
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7341804.html
Copyright © 2020-2023  润新知