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\n", 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\n",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], " \n"[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\n", 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, " \n"[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\n", 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\n", DP1(cnt));
79         }
80     }
81     return 0;
82 }
View Code

 

posted @ 2018-08-24 17:11  Dup4  阅读(1001)  评论(0编辑  收藏  举报