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题:

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

  • 相关阅读:
    606. Construct String from Binary Tree
    696. Count Binary Substrings
    POJ 3255 Roadblocks (次短路)
    POJ 2823 Sliding Window (单调队列)
    POJ 1704 Georgia and Bob (博弈)
    UVa 1663 Purifying Machine (二分匹配)
    UVa 10801 Lift Hopping (Dijkstra)
    POJ 3281 Dining (网络流之最大流)
    UVa 11100 The Trip, 2007 (题意+贪心)
    UVaLive 4254 Processor (二分+优先队列)
  • 原文地址:https://www.cnblogs.com/ZKin/p/9507491.html
Copyright © 2011-2022 走看看