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\n", max_num);
    return 0;
}

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\n%d\n", val, cost);
91     }
92 }

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\n", l);
    }
    return 0;
}

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\n", ans - tmp);
    return 0;
}

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\n", 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;
}

K题:

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

原文地址:https://www.cnblogs.com/ZKin/p/9507491.html

时间: 2024-10-07 17:10:08

ACM-ICPC SouthWestern Europe Regional Contest 2017题解的相关文章

ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Krak&#243;w

ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik's RectangleProblem B: What does the fox say?Problem C: Magical GCDProblem D: SubwayProblem E: EscapeProblem F: DraughtsProblem G: History courseProblem H: C

ICPC North Central NA Contest 2017 部分题解

ICPC North Central NA Contest 2017 部分题解 B. Pokemon Go Go 大意:用最短路径来抓住所有的稀有精灵,DFS求最短路 #include <bits/stdc++.h> #define mem(a) memset(a,0,sizeof(a)) #define forn(i,n) for(int i=0;i<n;++i) #define for1(i,n) for(int i=1;i<=n;++i) #define IO std::io

2018-2019, ICPC, Asia Yokohama Regional Contest 2018 (Gym - 102082)

2018-2019, ICPC, Asia Yokohama Regional Contest 2018 A - Digits Are Not Just Characters 签到. B - Arithmetic Progressions 题意:从给定的集合中选出最多的数构成等差数列. 题解:数字排序后,设\(dp[i][j]\)表示等差数列最后一个数字为\(a[i]\),倒数第二个数字为\(a[j]\)的最大个数.然后对于每一位枚举 \(i\),\(lower\_bound()\)找有无合法的

2019-2020 ICPC Southwestern European Regional Programming Contest (SWERC 2019-2020)

J想到了卡特兰数,也想到要按最小值分割数组,丢给队友之后两个人都没做出来,傻了 题目链接:https://codeforces.com/gym/102501 B: solver:czq 1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define pb emplace_back 6 #define mp make_pair 7 #define eps 1e-8 8

April Fools Contest 2017 题解&amp;源码(A,数学 B,数学 C,数学 D,字符串 E,数字逻辑 F,排序,卡时间)

A. Numbers Joke time limit per test:2 seconds memory limit per test:64 megabytes input:standard input output:standard output Input The input contains a single integer a (1 ≤ a ≤ 30). Output Output a single integer. Example Input 3 Output 27 题目链接:http

2019-2020 ICPC, Asia Jakarta Regional Contest H. Twin Buildings

As you might already know, space has always been a problem in ICPC Jakarta. To cope with this, ICPC Jakarta is planning to build two new buildings. These buildings should have a shape of a rectangle of the same size. Now, their problem is to find lan

ICPC North Central NA Contest 2017

https://www.jisuanke.com/contest/7331?view=challenges G. Sheba's Amoebas 题意:给定一个图,求图里有几个封闭图形 思路:用DFS每次将一整块连通图标记,最后看标记了多少个 直接上代码: #include <bits/stdc++.h> using namespace std; typedef long long ll; //typedef pair<ll,ll> PAIR; const int maxn = 1

2015-2016 ACM-ICPC, Central Europe Regional Contest (CERC 15)

地址 Rank Solved A B C D E F G H I J K L 62/217 5/12 O O . O . O . . . . O . O: 当场通过 ?: 赛后通过 .: 尚未通过 A ASCII Addition solved by chelly chelly's solution B Book Borders solved by chelly chelly's solution C Cow Confinement unsolved D Digit Division solve

2018 ICPC Asia Jakarta Regional Contest

题目传送门 题号 A B C D E F G H I J K L 状态 Ο . . Ο . . . . Ο . . Ο Ο:当场 Ø:已补 .  :  待补 A. Edit Distance Thinking:kk pai爷 Code:kk 不能直接反转,比如"010101",直接反转后就变成"101010",右移一位,然后加个0就可以了. 所以要先统计01的数量,如果0大于1,就全变成1,1大于0,就全变成0(从数量上的改变就大于s/2了),相等的话,就看首位是0