zoukankan      html  css  js  c++  java
  • ACM-ICPC SouthWestern Europe Regional Contest 2017题解

    题目地址 
    http://codeforces.com/gym/101635/

    A 题:

    计算两个数组元素之间最有可能的差值,注意数据全部非法时的情况

    #include<bits/stdc++.h>
    using namespace std;
    const int  maxn = 2005;
    int a[maxn], b[maxn];
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        unordered_map<int, int> mp;
        for (int i = 0; i < n; ++i) {
            scanf("%d", a + i);
        }
        for (int i = 0; i < m; ++i) {
            scanf("%d", b + i);
            for (int j = 0; j < n; ++j) {
                if (a[j] > b[i])
                    break;
                ++mp[b[i] - a[j]];
            }
        }
        int max_num = 0, max_cnt = 0;
        for (auto i : mp) {
            if (max_cnt < i.second || max_cnt == i.second && i.first < max_num) {
                max_cnt = i.second;
                max_num = i.first;
            }
        }
        printf("%d
    ", max_num);
        return 0;
    }
    View Code

    B 题:

    C题:

    用1*2 或者 1 * 1的矩形块覆盖n * m的矩形,求出所有可能的摆放方式总数(mod 1e9),通过状压DP计算n = 1 ~ 8条件下的递推式f(n),根据递推式运用矩阵快速幂计算出F(n)的值

    D题: 

    E题:

    给出一个菜谱的有向无环图,有每种菜的花费以及这种菜所依赖的菜的花费和价值,要求最终的菜单中每种菜只能出现一次,问在花费不超过B的前提下,价值和最大。
    一种菜的合成受限于另一种菜,容易想到拓扑排序,根据拓扑排序的性质,可以得到每种菜最小的合成代价,然后01背包即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e6 + 7;
     4 typedef long long ll;
     5 const int inf = 0x3f3f3f3f;
     6 char s1[maxn][25];
     7 char s2[maxn][25];
     8 char s3[maxn][25];
     9 int c[maxn];
    10 int v[maxn];
    11 int cc[maxn];
    12 int vv[maxn];
    13 int in[maxn];
    14 int sta[maxn];
    15 map<string, int>mp;
    16 vector<pair<int, int> >a[maxn];
    17 int ID;
    18 int B, n;
    19 bool e[maxn];
    20 ll dp[maxn];
    21 
    22 int getid(char s[]) {
    23     if (!mp.count(s)) {
    24         mp[s] = ++ID;
    25         a[ID].clear();
    26         cc[ID] = inf;
    27         vv[ID] = -inf;
    28         in[ID] = 0;
    29     }
    30     return mp[s];
    31 }
    32 
    33 int main() {
    34     while (~scanf("%d%d", &B, &n)) {
    35         mp.clear();
    36         ID = 0;
    37         for (int i = 1; i <= n; i++) {
    38             scanf("%s%s%s%d%d", s1[i], s2[i], s3[i], &c[i], &v[i]);
    39             int z = getid(s1[i]);
    40             int x = getid(s2[i]);
    41             int y = getid(s3[i]);
    42             ++in[z];
    43             a[x].push_back({ y,i });
    44             a[y].push_back({ x,i });
    45             e[i] = 0;
    46         }
    47         int top = 0;
    48         for (int i = 1; i <= ID; i++) {
    49             if (in[i] == 0) {
    50                 sta[++top] = i;
    51                 cc[i] = vv[i] = 0;
    52             }
    53         }
    54         while (top) {
    55             int x = sta[top--];
    56             for (auto it : a[x]) {
    57                 int y = it.first;
    58                 int o = it.second;
    59                 if (!e[o] && in[y] == 0) {
    60                     e[o] = 1;
    61                     int z = mp[s1[o]];
    62                     int cost = cc[x] + cc[y] + c[o];
    63                     int val = vv[x] + vv[y] + v[o];
    64                     if (cost<cc[z] || cost == cc[z] && val>vv[z]) {
    65                         cc[z] = cost;
    66                         vv[z] = val;
    67                     }
    68                     if (--in[z] == 0) {
    69                         sta[++top] = z;
    70                     }
    71                 }
    72             }
    73         }
    74         memset(dp, 0, sizeof(dp));
    75         dp[0] = 0;
    76         for (int i = 1; i <= ID; ++i) {
    77             for (int j = B; j >= cc[i]; --j) {
    78                 dp[j] = max(dp[j], dp[j - cc[i]] + vv[i]);
    79             }
    80         }
    81         
    82         int cost = 0;
    83         ll val = 0;
    84         for (int i = 1; i <= B; i++) {
    85             if (dp[i] > val) {
    86                 val = dp[i];
    87                 cost = i;
    88             }
    89         }
    90         printf("%lld
    %d
    ", val, cost);
    91     }
    92 }
    View Code

    F题:

    根据 x * y 的和除以w即可得出 L的值

    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    const int  maxn = 2005;
    int main() {
        int w,l;
        while (~scanf("%d", &w)) {
            int n;
            scanf("%d", &n);
            ll sum = 0;
            while (n--) {
                int x, y;
                scanf("%d%d", &x, &y);
                sum += x * y;
            }
            l = sum / w;
            printf("%d
    ", l);
        }
        return 0;
    }
    View Code

    G题:

    有两种跑匹配的方法,一种是找到有可能对答案做出贡献的快递员到货物的路线建二分图,左边是快递员,右边是货物,权值设置为 len(r->b) - len(c->b),跑一遍最大权值匹配(特判二分图无边的情况,因为最少需要1个快递员运送货物)。
    另外一种更简单的方法是是我们建两组点,一组是快递员和n-1个饭店,一组是货物,分别连接快递员到货物,饭店到货物的边,跑一边最大权值匹配。当然这题也可以用最小费用流来做,但需要优化添边的数目以免超时。

    #pragma warning(disable:4996)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef pair<int, int> pii;
    typedef pair<double, int>pdi;
    #define ll long long
    #define CLR(a,b) memset(a,b,sizeof(a))
    #define _for(i, a, b) for (int i = a; i < b; ++i)
    const int  mod = (int)1e9 + 7;
    const int  maxn = 2005;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    struct node
    {
        int x, y;
    };
    struct bc_edge {
        int dif, bottle, cart;
        bool operator<(const bc_edge & r) const {
            return dif < r.dif;
        }
    };
    int cal_dist(node l, node r) {
        return abs(l.x - r.x) + abs(l.y - r.y);
    }
    node a[maxn], b[maxn];
    int dis[maxn];
    const int N = 2005;
    const int INF = 0x3f3f3f3f;
    int nx, ny;//两边的点数
    int g[N][N];//二分图描述
    int linker[N], lx[N], ly[N];//y中各点匹配状态,x,y中的点标号
    int slack[N];
    bool visx[N], visy[N];
    bool DFS(int x)
    {
        visx[x] = true;
        for (int y = 0; y < ny; y++)
        {
            if (visy[y])continue;
            int tmp = lx[x] + ly[y] - g[x][y];
            if (tmp == 0)
            {
                visy[y] = true;
                if (linker[y] == -1 || DFS(linker[y]))
                {
                    linker[y] = x;
                    return true;
                }
            }
            else if (slack[y] > tmp)
                slack[y] = tmp;
        }
        return false;
    }
    int KM()
    {
        memset(linker, -1, sizeof(linker));
        memset(ly, 0, sizeof(ly));
        for (int i = 0; i < nx; i++)
        {
            lx[i] = -INF;
            for (int j = 0; j < ny; j++)
                if (g[i][j] > lx[i])
                    lx[i] = g[i][j];
        }
        for (int x = 0; x < nx; x++)
        {
            for (int i = 0; i < ny; i++)
                slack[i] = INF;
            while (true)
            {
                memset(visx, false, sizeof(visx));
                memset(visy, false, sizeof(visy));
                if (DFS(x))break;
                int d = INF;
                for (int i = 0; i < ny; i++)
                    if (!visy[i] && d > slack[i])
                        d = slack[i];
                for (int i = 0; i < nx; i++)
                    if (visx[i])
                        lx[i] -= d;
                for (int i = 0; i < ny; i++)
                {
                    if (visy[i])ly[i] += d;
                    else slack[i] -= d;
                }
            }
        }
        int res = 0;
        for (int i = 0; i < ny; i++)
            if (linker[i] != -1)
                res += g[linker[i]][i];
        return res;
    }
    
    int main() {
        int n, m;
        int ans = 0;
        node t;
        scanf("%d%d", &n, &m);
        _for(i, 0, n)
            scanf("%d%d", &a[i].x, &a[i].y);
        _for(i, 0, m)
            scanf("%d%d", &b[i].x, &b[i].y);
        scanf("%d%d", &t.x, &t.y);
        _for(i, 0, n) {
            dis[i] = cal_dist(t, a[i]);
            ans += 2 * dis[i];
        }
        // cout << ans << endl;
        vector<bc_edge> v;
        _for(i, 0, n) {
            _for(j, 0, m) {
                int tmp = cal_dist(a[i], b[j]) - dis[i];
                v.push_back({ tmp, i, j });
            }
        }
        sort(begin(v), end(v));
        for (int i = 0; i < (int)v.size(); ++i) {
            if (v[i].dif < 0) {
                int x = v[i].bottle;
                int y = v[i].cart;
                g[x][y] = -v[i].dif;
            }
            else
                break;
        }
        nx = n + m, ny = n + m;
        int tmp = -v[0].dif;
        if (v[0].dif < 0) {
            tmp = KM();
        }
        printf("%d
    ", ans - tmp);
        return 0;
    }
    View Code

    H题:

    I题:

    J题:

    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define CLR(a,b) memset(a,b,sizeof(a))
    const int  mod = 1e9 + 7;
    const int  maxn = 2005;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    ll a[4], b[4], x, y;
    int c[4] = { 1,3,2 };
    int d[4] = { 2,1,3 };
    ll sum[5];
    ll chang, kuan;
    int n, i, j, f;
    int main() {
        chang = 0;
        kuan = 0;
        scanf("%d", &n);
        for (i = 1; i <= n; ++i) {
            scanf("%lld", &x);
            a[i % 3] += x;
        }
        for (i = 1; i <= n; ++i) {
            scanf("%lld", &x);
            b[i % 3] += x;
        }
        printf("%lld %lld %lld
    ", b[1] * a[2] + a[1] * b[2] + a[0] * b[0], b[2] * a[2] + a[0] * b[1] + a[1] * b[0], b[1] * a[1] + a[0] * b[2] + a[2] * b[0]);
        return 0;
    }
    View Code

    K题:

    求吹起最小的宽度,吹灭蛋糕上所有的蜡烛,用旋转卡壳做出凸包上每个点到另一线的距离的最小值即可

  • 相关阅读:
    Linux驱动学习时间、延迟及延缓操作3
    Windows 系统下Git安装图解
    [整理]Android Intent和PendingIntent的区别
    C++篇实现MD5算法
    重温数据结构——(2)
    重温数据结构——(1)
    红黑树——1.介绍与查找
    Ubuntu Telnet 服务
    文本框垂直居中
    文本框透明无边框
  • 原文地址:https://www.cnblogs.com/ZKin/p/9507491.html
Copyright © 2011-2022 走看看