2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017) Solution

A. Drawing Bordersnode

Unsolved.c++

 

B. Buildings閉包

Unsolved.ide

 

C. Joyrideui

Upsolved.spa

題意:3d

在遊樂園中,有n個遊玩設施,有些設施之間有道路,給出每一個設施須要花費的時間和價格,以及通過每條道路的時間,求從設施1出發剛好回到設施1剛好花費時間x的最小花費。code

思路:blog

$dist[i][j] 表示 第i個時刻 到第j個點的最小花費  從<t[1], 1> -> <x, 1>$排序

跑最短路便可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 3010
 5 #define ll long long
 6 #define INF 0x3f3f3f3f3f3f3f3f
 7 int X, n, m, T, t[N], p[N]; 
 8 vector <int> G[N];
 9 
10 struct node
11 {
12     int x, to; ll w;
13     node () {}
14     node (int x, int to, ll w) : x(x), to(to), w(w) {}
15     bool operator < (const node &r) const { return w > r.w; }
16 };
17 
18 bool used[N][N]; 
19 ll dist[N][N];
20 void Dijkstra()
21 {
22     for (int i = 1; i <= X; ++i) for (int j = 1; j <= n; ++j) dist[i][j] = INF, used[i][j] = 0;
23     priority_queue <node> q; q.emplace(t[1], 1, 0); dist[t[1]][1] = p[1]; 
24     while (!q.empty())
25     {
26         int x = q.top().x, u = q.top().to; q.pop();
27         if (x > X) continue;
28         if (used[x][u]) continue;
29         used[x][u] = 1;
30         if (!used[x + t[u]][u] && dist[x + t[u]][u] > dist[x][u] + p[u]) 
31         {
32             dist[x + t[u]][u] = dist[x][u] + p[u];
33             q.emplace(x + t[u], u, dist[x + t[u]][u]);
34         }
35         for (auto v : G[u]) if (!used[x + t[v] + T][v] && dist[x + t[v] + T][v] > dist[x][u] + p[v])
36         {
37             dist[x + t[v] + T][v] = dist[x][u] + p[v];
38             q.emplace(x + t[v] + T, v, dist[x + t[v] + T][v]);
39         }
40     }    
41 }
42 
43 int main()
44 {
45     while (scanf("%d", &X) != EOF)
46     {
47         scanf("%d%d%d", &n, &m, &T);
48         for (int i = 1, u, v; i <= m; ++i)
49         {
50             scanf("%d%d", &u, &v);
51             G[u].push_back(v);
52             G[v].push_back(u);
53         }
54         for (int i = 1; i <= n; ++i) scanf("%d%d", t + i, p + i);
55         Dijkstra();
56         if (dist[X][1] == INF) puts("It is a trap.");
57         else printf("%lld\n", dist[X][1]);
58     }
59     return 0; 
60 }
View Code

 

D. Pants On Fire

Solved.

題意:

給出一些關係,再給出一些關係的詢問,對於詢問給出三種結果。

思路:

Floyd求閉包,可是我仍是想知道爲何拓撲排序不行,難道是題意讀錯,它不必定是個DAG?

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 410
 5 int n, m; 
 6 map <string, int> mp; int cnt; 
 7 char a[N], b[N];
 8 int G[N][N]; 
 9 
10 int getid(char *s)
11 {
12     if (mp.find(s) == mp.end()) mp[s] = ++cnt;
13     return mp[s];
14 }
15 
16 void Floyd()
17 {
18     for (int k = 1; k <= cnt; ++k)
19     {
20         for (int i = 1; i <= cnt; ++i)
21         {
22             for (int j = 1; j <= cnt; ++j)
23             {
24                 if (G[i][k] & G[k][j])
25                     G[i][j] = 1;
26             }
27         }
28     }
29 }
30 
31 void init()
32 {
33     memset(G, 0, sizeof G); 
34     mp.clear(); cnt = 0; 
35 }
36 
37 int main()
38 {
39     while (scanf("%d%d", &n, &m) != EOF)
40     {
41         init();
42         for (int i = 1, u, v; i <= n; ++i)
43         {
44             scanf("%s are worse than %s", a, b);
45             u = getid(a), v = getid(b);
46             G[u][v] = 1;
47         }
48         Floyd(); 
49         //for (auto it : mp) cout << it.first << " " << rt[it.second] << " " << deep[it.second] << endl;
50         for (int i = 1, u, v; i <= m; ++i)
51         {
52             scanf("%s are worse than %s", a, b);
53             u = getid(a), v = getid(b);
54             if (G[u][v] == 1) puts("Fact");
55             else if (G[v][u] == 1) puts("Alternative Fact");
56             else puts("Pants on Fire");
57         }
58     }
59     return 0;
60 }
View Code

 

E. Perpetuum Mobile

Upsolved.

題意:

有n個轉換器,m個轉換關係,轉換關係是有向邊

求從哪一個點出發回到起點後通過的轉換大於原來的值

思路:

枚舉起點跑最長路,乘法能夠取個$log$, 固然也能夠再取個負跑最短路也能夠

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 10010
 5 #define INF 0x3f3f3f3f
 6 #define pid pair <int, double>
 7 int n, m;
 8 vector <pid> G[N];
 9 
10 struct node
11 {
12     int to; double w;
13     node () {}
14     node (int to, double w) : to(to), w(w) {}
15     bool operator < (const node &r) const { return w < r.w; }
16 };
17 
18 double dist[N]; bool used[N];
19 bool Dijkstra(int st)
20 {
21     for (int i = 1; i <= n; ++i) dist[i] = 0.0, used[i] = false;
22     priority_queue <node> q; q.emplace(st, 0);  
23     while (!q.empty())
24     {
25         int u = q.top().to; q.pop(); 
26         if (used[u] && u == st && dist[u] > 0) return false;  
27         if (used[u]) continue;
28         used[u] = 1;
29         for (auto it : G[u]) if (dist[it.first] < dist[u] + log(it.second)) 
30         {
31             dist[it.first] = dist[u] + log(it.second);
32             q.emplace(it.first, dist[it.first]);
33         }
34     }    
35     return true;
36 }
37 
38 bool solve()
39 {
40     for (int i = 1; i <= n; ++i) if (Dijkstra(i) == false)
41         return false; 
42     return true;
43 }
44 
45 int main()
46 {
47     while (scanf("%d%d", &n, &m) != EOF)
48     {
49         for (int i = 1; i <= n; ++i) G[i].clear();
50         double w;
51         for (int i = 1, u, v; i <= m; ++i)
52         {
53             scanf("%d%d%lf", &u, &v, &w);
54             G[u].emplace_back(v, w);
55         }
56         if (solve() == false) printf("in");
57         puts("admissible");
58     }
59     return 0;
60 }
View Code

 

F. Plug It In

Unsolved.

題意:

給出一個匹配關係,能夠設置一我的和三我的匹配,求最大匹配數。

思路:

先求最大匹配,再枚舉每一個插座,找增廣路,枚舉點的時候都要複製原圖備份一下

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 1510
 5 int n, m, k;
 6 vector <int> G[N];
 7 int linker[N], vis[N], tmp[N];
 8 
 9 bool DFS(int u)
10 {
11     for (auto v : G[u]) if (!vis[v])
12     {
13         vis[v] = 1; 
14         if (linker[v] == -1 || DFS(linker[v]))
15         {
16             linker[v] = u;
17             return true;
18         }
19     }
20     return false;
21 }
22 
23 int main()
24 {
25     while (scanf("%d%d%d", &n, &m, &k) != EOF)
26     {
27         for (int i = 1; i <= n; ++i) G[i].clear();
28         for (int i = 1, u, v; i <= k; ++i)
29         {
30             scanf("%d%d", &u, &v);
31             G[u].push_back(v);
32         }
33         memset(linker, -1, sizeof linker);
34         int res = 0, ans = 0;
35         for (int i = 1; i <= n; ++i)
36         {
37             memset(vis, 0, sizeof vis);
38             if (DFS(i)) ++res;
39         }
40         memcpy(tmp, linker, sizeof linker);
41         for (int i = 1; i <= n; ++i)
42         {
43             int cnt = 0;
44             for (int j = 1; j <= 2; ++j)
45             {
46                 memset(vis, 0, sizeof vis);
47                 if (DFS(i)) ++cnt;    
48             }
49             ans = max(ans, cnt);
50             memcpy(linker, tmp, sizeof tmp);
51         }
52         printf("%d\n", res + ans);
53     }
54     return 0;
55 }
View Code

 

G. Water Testing

Upsolved.

題意:求一個多邊形內部整點個數。

思路:

皮克定理:$S = a + \frac{b}{2} - 1   S表示多邊形面積,\frac{b}{2} 表示 多邊形邊上的整點數   a 表示多邊形內部整點數$

由於點是按順序給出,有求面積公式$S = \frac{1}{2} \sum_{i = 0}^{i = n}|\vec{P_i} x \vec{P_i - 1}|$

再考慮 線段上的整點個數爲

$令 a = abs(stx - edx), b = abs(sty - edy),整點個數爲gcd(a, b) + 1$

考慮證實:

根據直線兩點式有:

$y - y_1 = \frac{y_2 - y_1}{x_2 - x_1} \cdot (x - x _1)$

移項得

$y = \frac{y_2 - y_1}{x_2 - x_1} \cdot (x - x_1) + y_1$

即考慮 有多少個$x使得 (x - x_1) \equiv 0 \pmod {x_2 - x_1}$

因爲 $x 在 [x1, x2] 範圍內 那麼 (x - x_1) 的範圍即 [0, x2 - x1]$

$考慮 \frac{y_2 - y_1}{x_2 - x_1} 能夠跟他們的gcd約分$

$\frac{x_2 - x_1}{ \frac {x_2 - x_1}{gcd((y_2 - y_1), (x_2 - x_1))}} = gcd((y_2 - y_1), (x_2 - x_1))$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 100010
 5 #define ll long long
 6 int n; 
 7 ll x[N], y[N];
 8 
 9 ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a;}
10 
11 int main()
12 {
13     while (scanf("%d", &n) != EOF)
14     {
15         for (int i = 1; i <= n; ++i)
16             scanf("%lld%lld", x + i, y + i);
17         x[0] = x[n]; y[0] = y[n];
18         ll s = 0, b = 0;
19         for (int i = 1; i <= n; ++i)
20         {
21             s += x[i - 1] * y[i] - x[i] * y[i - 1];
22             ll A = abs(x[i] - x[i - 1]);
23             ll B = abs(y[i] - y[i - 1]);
24             b += gcd(A, B);
25         }
26         s = abs(s); 
27         printf("%lld\n", (s - b + 2) >> 1);  
28     }
29     return 0;
30 }
View Code

 

 

H. Ratatoskr

Unsolved.

 

I. Uberwatch

Water.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 300010
 5 int n, m, x[N], Max[15];
 6 
 7 int main()
 8 {
 9     while (scanf("%d%d", &n, &m) != EOF)
10     {
11         memset(Max, 0, sizeof Max);
12         for (int i = 1; i <= n; ++i) scanf("%d", x + i);
13         for (int i = m + 1, res; i <= n; ++i)
14         {
15             res = x[i] + Max[m];
16             for (int j = m; j >= 1; --j) Max[j] = max(Max[j], Max[j - 1]);
17             Max[1] = max(Max[1], res);
18         }
19         printf("%d\n", *max_element(Max + 1, Max + 1 + m));
20     }
21     return 0;
22 }
View Code

 

J. Word Clock

Unsolved.

 

K. You Are Fired

Water.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 10010
 5 int n, k, d;
 6 struct node
 7 {
 8     char s[10]; int c;
 9     void scan()
10     {
11         scanf("%s%d", s, &c);
12     }
13     bool operator < (const node &r) const {return c > r.c;}
14 }emp[N];
15 
16 int main()
17 {
18     while (scanf("%d%d%d", &n, &d, &k) != EOF)
19     {
20         for (int i = 1; i <= n; ++i) emp[i].scan();
21         sort(emp + 1, emp + 1 + n);
22         int tot = 0;
23         for (int i = 1; i <= k; ++i) tot += emp[i].c;
24         if (tot < d) puts("impossible");
25         else
26         {
27             printf("%d\n", k);
28             for (int i = 1; i <= k; ++i) printf("%s, YOU ARE FIRED!\n", emp[i].s);
29         }
30     }
31     return 0;
32 }
View Code
相關文章
相關標籤/搜索