• 2017 Benelux Algorithm Programming Contest (BAPC 17) Solution


    A - Amsterdam Distance

    题意:极坐标系,给出两个点,求最短距离

    思路:只有两种方式,取min  第一种,先走到0点,再走到终点 第二种,走到同一半径,再走过去

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 #define INF 0x3f3f3f3f
     5 
     6 const double PI = acos(-1.0);
     7 
     8 double n, m, r;
     9 double n1, m1, n2, m2;
    10 
    11 inline double work1()
    12 {
    13     double dis1 = r * n1 / n;
    14     double dis2 = r * n2 / n;
    15     return dis1 + dis2;
    16 }
    17 
    18 inline double work2()
    19 {
    20     double dis1 = r * (n2 - n1) / n;
    21     double dis2 = fabs(m1 - m2) * r * n1 * PI/ (n * m);
    22     return dis1 + dis2;    
    23 }
    24 
    25 int main()
    26 {
    27     while (scanf("%lf%lf%lf", &m, &n, &r) != EOF)
    28     {
    29         scanf("%lf%lf%lf%lf", &m1, &n1, &m2, &n2);
    30         if (n1 > n2) 
    31         {
    32             swap(n1, n2);
    33             swap(m1, m2);
    34         }
    35         double ans = INF * 1.0;
    36         ans = min(ans, work1());
    37         ans = min(ans, work2());
    38         printf("%.10f
    ", ans);
    39     }
    40     return 0;
    41 }
    View Code

    B - Bearly Made It

    留坑。

    C - Collatz Conjecture

    题意:给出n个数,求有多少个不同的区间gcd

    思路:从头扫过去,每次扩展gcd,如果有重复的直接剪掉

    因为假设扫到第i个的时候,有x个gcd  那么到第i个,这x个gcd 如果都被保留下来,那么第i个数一定要是这n个数的倍数,那么显然如果存在这样的数,那么当x > 30 的时候 早就爆 1e18 了 所以复杂度应该在 30 * (n) * log(n)

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define N 500050
     6 
     7 typedef long long ll;
     8 
     9 inline ll gcd(ll a, ll b)
    10 {
    11     return b == 0 ? a : gcd(b, a % b);
    12 }
    13 
    14 int n;
    15 ll GCD[N];
    16 ll num;
    17 map<ll, int>mp;
    18 
    19 int main()
    20 {
    21     while(~scanf("%d" ,&n))
    22     {
    23         mp.clear();
    24         int len = 0;
    25         for(int i = 1; i <= n; ++i)
    26         {
    27             scanf("%lld", &num);
    28             for(int j = 0; j < len; ++j)
    29             {
    30                 GCD[j] = gcd(GCD[j], num);
    31             }
    32             GCD[len++] = num;
    33             sort(GCD, GCD + len);
    34             int tmp = 0;
    35             for(int i = 0; i< len; ++i)
    36             {
    37                 mp[GCD[i]]++;
    38                 if(i == 0)
    39                 {
    40                     GCD[tmp++] = GCD[i];
    41                     continue;
    42                 }
    43                 if(GCD[i] == GCD[i - 1]) continue;
    44                 else GCD[tmp++] = GCD[i];
    45             }
    46             len = tmp;
    47         }
    48         int ans = mp.size();
    49         printf("%d
    ",ans);
    50     }
    51     return 0;
    52 }
    View Code

    D - Detour

    题意:给出n条路,每次选择的路都不选从这条路到0的最短路径上的路,求最后选的最短路径

    思路:先从1反向跑最短路,然后删边,再从0正向跑

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define N 100010
      5 #define M 1000010
      6 #define ll long long
      7 #define INFLL 0x3f3f3f3f3f3f3f3f
      8 
      9 struct Edge
     10 {
     11     int to, nx, flag;
     12     ll w;
     13     inline Edge() {}
     14     inline Edge(int to, ll w, int nx, int flag) : to(to), w(w), nx(nx), flag(flag) {}
     15 }edge[M << 1];
     16 
     17 int head[N], pos;
     18 
     19 inline void Init()
     20 {
     21     memset(head, -1, sizeof head);
     22     pos = 0;
     23 }
     24 
     25 inline void addedge(int u, int v, ll w)
     26 {
     27     edge[++pos] = Edge(v, w, head[u], 0); head[u] = pos;
     28     edge[++pos] = Edge(u, w, head[v], 0); head[v] = pos;
     29 }
     30 
     31 int n, m;
     32 
     33 struct node
     34 {
     35     int to; ll w;
     36     inline node() {}
     37     inline node(int to, ll w) : to(to), w(w) {}
     38     inline bool operator < (const node &r) const
     39     {
     40         return w > r.w;
     41     }
     42 };
     43 
     44 ll dist[N];
     45 int pre[N];
     46 bool used[N];
     47 
     48 inline void Dijkstra(int st)
     49 {
     50     for (int i = 0; i < n; ++i) dist[i] = INFLL, used[i] = false, pre[i] = -1;
     51     dist[st] = 0;
     52     priority_queue <node> q; q.emplace(st, 0);
     53     while (!q.empty())
     54     {
     55         int u = q.top().to; q.pop();
     56         used[u] = true;
     57         for (int it = head[u]; ~it; it = edge[it].nx)
     58         {
     59             if (edge[it].flag) continue;
     60             int v = edge[it].to; ll w = edge[it].w;
     61             if (!used[v] && dist[u] + w < dist[v])
     62             {
     63                 dist[v] = dist[u] + w;
     64                 pre[v] = u;
     65                 q.emplace(v, dist[v]);
     66             }
     67         }
     68     }
     69 }
     70 
     71 
     72 int main()
     73 {
     74     while (scanf("%d%d", &n, &m) != EOF)
     75     {
     76         ll w; Init();
     77         for (int i = 1, u, v; i <= m; ++i)
     78         {
     79             scanf("%d%d%lld", &u, &v, &w);
     80             addedge(u, v, w);
     81         }
     82         Dijkstra(1);
     83         if (dist[0] == INFLL)
     84         {
     85             puts("impossible");
     86             continue;
     87         }
     88         for (int i = 0; i < n; ++i)
     89         {
     90             for (int it = head[i]; ~it; it = edge[it].nx)
     91             {
     92                 int v = edge[it].to;
     93                 if (v == pre[i])
     94                 {
     95                     edge[it].flag = 1;
     96                     break;
     97                 }
     98             }
     99         }
    100         Dijkstra(0);
    101         if (dist[1] == INFLL)
    102         {
    103             puts("impossible");
    104             continue;
    105         }
    106         vector <int> ans;
    107         int it = 1;
    108         while (it != -1)
    109         {
    110             ans.push_back(it);
    111             it = pre[it];
    112         }    
    113         reverse(ans.begin(), ans.end());
    114         int len = ans.size();
    115         printf("%d ", len);
    116         for (int i = 0; i < len; ++i) printf("%d%c", ans[i], " 
    "[i == len - 1]);
    117 
    118     }
    119     return 0;
    120 }
    View Code

    E - Easter Eggs

    留坑。

    F - Falling Apart

    水。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n;
     6 int arr[20];
     7 
     8 int main()
     9 {
    10     while (scanf("%d", &n) != EOF)
    11     {
    12         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
    13         sort(arr + 1, arr + 1 + n);
    14         int ans[2] = {0, 0};
    15         int flag = 0;
    16         for (int i = n; i >= 1; --i)
    17         {
    18             ans[flag] += arr[i];
    19             flag ^= 1;
    20         }
    21         printf("%d %d
    ", max(ans[0], ans[1]), min(ans[0], ans[1]));
    22     }
    23     return 0;
    24 }
    View Code

    G - Going Dutch

    留坑。

    H - Hoarse Horses

    留坑。

    I - Irrational Division

    题意:给出n * m 的矩形,单位边长为1,黑白交替,Alice 只能一列一列取(从左往右),Bob只能一行一行取(从下往上),取到的分数为黑块-白块,求Alice 和 Bob 的最大分差,两人操作都最优

    思路:可以找一下规律,偶数行 答案是0

    奇数行 奇数列 答案是1

    奇数行 偶数列  行 < 列 答案是2 否则 答案是0

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n, m;
     6 
     7 int main()
     8 {
     9     while (scanf("%d%d", &n, &m) != EOF)
    10     {
    11         if ((n & 1) == 0)
    12         {
    13             puts("0");
    14             continue;
    15         }
    16         if ((m & 1))
    17         {
    18             puts("1");
    19             continue;
    20         }
    21         puts(n < m ? "2" : "0");
    22     }
    23     return 0;
    24 }
    View Code

    J - Jumping Choreography

    留坑。

    K - King of the Waves

    题意:给出n个人的胜负关系,打擂台赛,求最后0胜利,给出上场顺序

    思路:输出DFS序

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define N 1010
     6 
     7 int n;
     8 int tot = 0;
     9 int dep[N];
    10 char mp[N][N];
    11 int ans[N];
    12 
    13 inline void DFS(int pos, int cnt)
    14 {
    15     dep[pos] = cnt;
    16     ans[++tot] = pos;
    17     for(int i = 1; i <= n; ++i)
    18     {
    19         if(mp[pos][i] == '1' && !dep[i])
    20         {
    21             DFS(i, cnt + 1);
    22         }
    23     }
    24 }
    25 
    26 int main()
    27 {
    28     while(~scanf("%d", &n))
    29     {
    30         tot = 0;
    31         memset(dep, 0 , sizeof dep);
    32         for(int i = 1; i <= n; ++i)
    33         {
    34             for(int j = 1; j <= n; ++j)
    35             {
    36                 scanf(" %c", &mp[i][j]);
    37             }
    38         }
    39         DFS(1, 1);
    40         if(tot != n)
    41         {
    42             puts("impossible");
    43         }
    44         else
    45         {
    46             for(int i = n; i >= 1; --i)
    47             {
    48                 printf("%d%c", ans[i] - 1, " 
    "[i == 1]);
    49             }
    50         }
    51     }
    52     return 0;
    53 }
    View Code

    L - Lemonade Trade

    题意:给出n个兑换关系,刚开始有1l pink  最后想换到blue 要依次换,可以选择换和不换

    思路:O(n) 扫一下,记录在这之前被兑换的颜色饮料最多能被换到多少 然后取max  注意 不能直接乘法,取log 再取e的幂次

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define N 100010
     6 
     7 const int INF = 0x3f3f3f3f;
     8 const double EI = exp(1.0);
     9 
    10 int cnt;
    11 map<string, int >mp;
    12 double ans[N];
    13 
    14 inline void init()
    15 {
    16     mp.clear();
    17     cnt = 1;
    18     mp["pink"] = cnt++;
    19     mp["blue"] = cnt++;
    20     ans[1] = log(1.0);
    21     ans[2] = -INF * 1.0;
    22 }
    23 
    24 int n;
    25 string a, b;
    26 double w;
    27 
    28 int main()
    29 {
    30     ios::sync_with_stdio(false);
    31     cin.tie(0);cout.tie(0);
    32     while(cin >> n)
    33     {
    34         init();
    35         for(int i = 1; i <= n; ++i)
    36         {
    37             cin >> a >> b >> w;
    38             if(mp[a] == 0)
    39             {
    40                 mp[a] = cnt++;
    41                 ans[mp[a]] = -INF * 1.0;
    42             }
    43             if(mp[b] == 0)
    44             {
    45                 mp[b] = cnt++;
    46                 ans[mp[b]] = -INF * 1.0;
    47             }
    48             int id1 = mp[a], id2 = mp[b];
    49             ans[id1] = max(ans[id1], ans[id2] + log(w));
    50         }
    51         ans[2] = pow(EI, ans[2]);
    52         ans[2] = min(ans[2], 10.0);
    53         cout << setiosflags(ios::fixed) << setprecision(10) << ans[2] << endl;
    54     }
    55     return 0;
    56 }
    View Code

    M - Manhattan Mornings

    题意:给出n个点,起始点和终点,求从起始点到终点的最短路径,最多经过多少点

    思路:先排序,固定一个轴,再求最长上升子序列

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 100010
     5 
     6 int n;
     7 
     8 struct node
     9 {
    10     int x, y;
    11     inline void scan()
    12     {
    13         scanf("%d%d", &x, &y);
    14     }
    15     inline bool operator < (const node &r) const
    16     {
    17         return x < r.x || x == r.x && y < r.y;
    18     }
    19 }point[N], st, ed;
    20 
    21 int arr[N], brr[N];
    22 
    23 inline int DP1(int n)
    24 {
    25     if (n == 0) return 0;
    26     int i, len, pos;
    27     brr[1] = arr[1];
    28     len = 1;
    29     for (int i = 2; i <= n; ++i)
    30     {
    31         if (arr[i] >= brr[len])
    32         {
    33             len = len + 1;
    34             brr[len] = arr[i];
    35         }
    36         else
    37         {
    38             int pos = upper_bound(brr + 1, brr + 1 + len, arr[i]) - brr;
    39             brr[pos] = arr[i];
    40         }
    41     }
    42     return len;
    43 }
    44 
    45 inline bool cmp (node a, node b)
    46 {
    47     return a.x > b.x || a.x == b.x && a.y < b.y;
    48 }
    49 
    50 int main()
    51 {
    52     while (scanf("%d", &n) != EOF)
    53     {
    54         st.scan(); ed.scan();
    55         for (int i = 1; i <= n; ++i)
    56             point[i].scan();
    57         if (st.x > ed.x) swap(st, ed);
    58         if (st.y < ed.y)
    59         {
    60             sort(point + 1, point + 1 + n);
    61             int cnt = 0;
    62             for (int i = 1; i <= n; ++i)
    63             {
    64                 if (point[i].x >= st.x && point[i].x <= ed.x && point[i].y >= st.y && point[i].y <= ed.y)
    65                     arr[++cnt] = point[i].y;
    66             }
    67             printf("%d
    ", DP1(cnt));
    68         }
    69         else
    70         {
    71             sort(point + 1, point + 1 + n, cmp);
    72             int cnt = 0;
    73             for (int i = 1; i <= n; ++i)
    74             {
    75                 if (point[i].x >= st.x && point[i].x <= ed.x && point[i].y >= ed.y && point[i].y <= st.y)
    76                     arr[++cnt] = point[i].y;
    77             }
    78             printf("%d
    ", DP1(cnt));
    79         }
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    matlab2016b和c# .net4.0混合编程
    有限元入门
    math.net 拟合
    excel 错误提示以及其他基础知识
    excel的小bug
    Servlet体系及方法
    Servlet学习笔记
    HTTP协议
    Tomcat
    反射
  • 原文地址:https://www.cnblogs.com/Dup4/p/9530962.html
Copyright © 2020-2023  润新知