2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017) Solution
A. Drawing Borders
Unsolved.
B. Buildings
Unsolved.
C. Joyride
Upsolved.
题意:
在游乐园中,有n个游玩设施,有些设施之间有道路,给出每个设施需要花费的时间和价格,以及经过每条道路的时间,求从设施1出发恰好回到设施1恰好花费时间x的最小花费。
思路:
$dist[i][j] 表示 第i个时刻 到第j个点的最小花费 从<t[1], 1> -> <x, 1>$
跑最短路即可
#include <bits/stdc++.h>
using namespace std; #define N 3010
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3f
int X, n, m, T, t[N], p[N];
vector <int> G[N]; struct node
{
int x, to; ll w;
node () {}
node (int x, int to, ll w) : x(x), to(to), w(w) {}
bool operator < (const node &r) const { return w > r.w; }
}; bool used[N][N];
ll dist[N][N];
void Dijkstra()
{
for (int i = ; i <= X; ++i) for (int j = ; j <= n; ++j) dist[i][j] = INF, used[i][j] = ;
priority_queue <node> q; q.emplace(t[], , ); dist[t[]][] = p[];
while (!q.empty())
{
int x = q.top().x, u = q.top().to; q.pop();
if (x > X) continue;
if (used[x][u]) continue;
used[x][u] = ;
if (!used[x + t[u]][u] && dist[x + t[u]][u] > dist[x][u] + p[u])
{
dist[x + t[u]][u] = dist[x][u] + p[u];
q.emplace(x + t[u], u, dist[x + t[u]][u]);
}
for (auto v : G[u]) if (!used[x + t[v] + T][v] && dist[x + t[v] + T][v] > dist[x][u] + p[v])
{
dist[x + t[v] + T][v] = dist[x][u] + p[v];
q.emplace(x + t[v] + T, v, dist[x + t[v] + T][v]);
}
}
} int main()
{
while (scanf("%d", &X) != EOF)
{
scanf("%d%d%d", &n, &m, &T);
for (int i = , u, v; i <= m; ++i)
{
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for (int i = ; i <= n; ++i) scanf("%d%d", t + i, p + i);
Dijkstra();
if (dist[X][] == INF) puts("It is a trap.");
else printf("%lld\n", dist[X][]);
}
return ;
}
D. Pants On Fire
Solved.
题意:
给出一些关系,再给出一些关系的询问,对于询问给出三种结果。
思路:
Floyd求闭包,但是我还是想知道为什么拓扑排序不行,难道是题意读错,它不一定是个DAG?
#include <bits/stdc++.h>
using namespace std; #define N 410
int n, m;
map <string, int> mp; int cnt;
char a[N], b[N];
int G[N][N]; int getid(char *s)
{
if (mp.find(s) == mp.end()) mp[s] = ++cnt;
return mp[s];
} void Floyd()
{
for (int k = ; k <= cnt; ++k)
{
for (int i = ; i <= cnt; ++i)
{
for (int j = ; j <= cnt; ++j)
{
if (G[i][k] & G[k][j])
G[i][j] = ;
}
}
}
} void init()
{
memset(G, , sizeof G);
mp.clear(); cnt = ;
} int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
init();
for (int i = , u, v; i <= n; ++i)
{
scanf("%s are worse than %s", a, b);
u = getid(a), v = getid(b);
G[u][v] = ;
}
Floyd();
//for (auto it : mp) cout << it.first << " " << rt[it.second] << " " << deep[it.second] << endl;
for (int i = , u, v; i <= m; ++i)
{
scanf("%s are worse than %s", a, b);
u = getid(a), v = getid(b);
if (G[u][v] == ) puts("Fact");
else if (G[v][u] == ) puts("Alternative Fact");
else puts("Pants on Fire");
}
}
return ;
}
E. Perpetuum Mobile
Upsolved.
题意:
有n个转换器,m个转换关系,转换关系是有向边
求从哪个点出发回到起点后经过的转换大于原来的值
思路:
枚举起点跑最长路,乘法可以取个$log$, 当然也可以再取个负跑最短路也可以
#include <bits/stdc++.h>
using namespace std; #define N 10010
#define INF 0x3f3f3f3f
#define pid pair <int, double>
int n, m;
vector <pid> G[N]; struct node
{
int to; double w;
node () {}
node (int to, double w) : to(to), w(w) {}
bool operator < (const node &r) const { return w < r.w; }
}; double dist[N]; bool used[N];
bool Dijkstra(int st)
{
for (int i = ; i <= n; ++i) dist[i] = 0.0, used[i] = false;
priority_queue <node> q; q.emplace(st, );
while (!q.empty())
{
int u = q.top().to; q.pop();
if (used[u] && u == st && dist[u] > ) return false;
if (used[u]) continue;
used[u] = ;
for (auto it : G[u]) if (dist[it.first] < dist[u] + log(it.second))
{
dist[it.first] = dist[u] + log(it.second);
q.emplace(it.first, dist[it.first]);
}
}
return true;
} bool solve()
{
for (int i = ; i <= n; ++i) if (Dijkstra(i) == false)
return false;
return true;
} int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
for (int i = ; i <= n; ++i) G[i].clear();
double w;
for (int i = , u, v; i <= m; ++i)
{
scanf("%d%d%lf", &u, &v, &w);
G[u].emplace_back(v, w);
}
if (solve() == false) printf("in");
puts("admissible");
}
return ;
}
F. Plug It In
Unsolved.
题意:
给出一个匹配关系,可以设置一个人和三个人匹配,求最大匹配数。
思路:
先求最大匹配,再枚举每个插座,找增广路,枚举点的时候都要复制原图备份一下
#include <bits/stdc++.h>
using namespace std; #define N 1510
int n, m, k;
vector <int> G[N];
int linker[N], vis[N], tmp[N]; bool DFS(int u)
{
for (auto v : G[u]) if (!vis[v])
{
vis[v] = ;
if (linker[v] == - || DFS(linker[v]))
{
linker[v] = u;
return true;
}
}
return false;
} int main()
{
while (scanf("%d%d%d", &n, &m, &k) != EOF)
{
for (int i = ; i <= n; ++i) G[i].clear();
for (int i = , u, v; i <= k; ++i)
{
scanf("%d%d", &u, &v);
G[u].push_back(v);
}
memset(linker, -, sizeof linker);
int res = , ans = ;
for (int i = ; i <= n; ++i)
{
memset(vis, , sizeof vis);
if (DFS(i)) ++res;
}
memcpy(tmp, linker, sizeof linker);
for (int i = ; i <= n; ++i)
{
int cnt = ;
for (int j = ; j <= ; ++j)
{
memset(vis, , sizeof vis);
if (DFS(i)) ++cnt;
}
ans = max(ans, cnt);
memcpy(linker, tmp, sizeof tmp);
}
printf("%d\n", res + ans);
}
return ;
}
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))$
#include <bits/stdc++.h>
using namespace std; #define N 100010
#define ll long long
int n;
ll x[N], y[N]; ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a;} int main()
{
while (scanf("%d", &n) != EOF)
{
for (int i = ; i <= n; ++i)
scanf("%lld%lld", x + i, y + i);
x[] = x[n]; y[] = y[n];
ll s = , b = ;
for (int i = ; i <= n; ++i)
{
s += x[i - ] * y[i] - x[i] * y[i - ];
ll A = abs(x[i] - x[i - ]);
ll B = abs(y[i] - y[i - ]);
b += gcd(A, B);
}
s = abs(s);
printf("%lld\n", (s - b + ) >> );
}
return ;
}
H. Ratatoskr
Unsolved.
I. Uberwatch
Water.
#include <bits/stdc++.h>
using namespace std; #define N 300010
int n, m, x[N], Max[]; int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
memset(Max, , sizeof Max);
for (int i = ; i <= n; ++i) scanf("%d", x + i);
for (int i = m + , res; i <= n; ++i)
{
res = x[i] + Max[m];
for (int j = m; j >= ; --j) Max[j] = max(Max[j], Max[j - ]);
Max[] = max(Max[], res);
}
printf("%d\n", *max_element(Max + , Max + + m));
}
return ;
}
J. Word Clock
Unsolved.
K. You Are Fired
Water.
#include <bits/stdc++.h>
using namespace std; #define N 10010
int n, k, d;
struct node
{
char s[]; int c;
void scan()
{
scanf("%s%d", s, &c);
}
bool operator < (const node &r) const {return c > r.c;}
}emp[N]; int main()
{
while (scanf("%d%d%d", &n, &d, &k) != EOF)
{
for (int i = ; i <= n; ++i) emp[i].scan();
sort(emp + , emp + + n);
int tot = ;
for (int i = ; i <= k; ++i) tot += emp[i].c;
if (tot < d) puts("impossible");
else
{
printf("%d\n", k);
for (int i = ; i <= k; ++i) printf("%s, YOU ARE FIRED!\n", emp[i].s);
}
}
return ;
}
2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017) Solution的更多相关文章
- (寒假开黑gym)2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)
layout: post title: (寒假开黑gym)2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017) au ...
- 2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)(9/11)
$$2017-2018\ ACM-ICPC\ German\ Collegiate\ Programming\ Contest (GCPC 2017)$$ \(A.Drawing\ Borders\) ...
- 2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)
A Drawing Borders 很多构造方法,下图可能是最简单的了 代码: #include<bits/stdc++.h> using namespace std; ; struct ...
- 2018 German Collegiate Programming Contest (GCPC 18)
2018 German Collegiate Programming Contest (GCPC 18) Attack on Alpha-Zet 建树,求lca 代码: #include <al ...
- (寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)
layout: post title: 2018 German Collegiate Programming Contest (GCPC 18) author: "luowentaoaa&q ...
- 2015 German Collegiate Programming Contest (GCPC 15) + POI 10-T3(12/13)
$$2015\ German\ Collegiate\ Programming\ Contest\ (GCPC 15) + POI 10-T3$$ \(A.\ Journey\ to\ Greece\ ...
- ACM ICPC, JUST Collegiate Programming Contest (2018) Solution
A:Zero Array 题意:两种操作, 1 p v 将第p个位置的值改成v 2 查询最少的操作数使得所有数都变为0 操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能 ...
- ACM ICPC, Amman Collegiate Programming Contest (2018) Solution
Solution A:Careful Thief 题意:给出n个区间,每个区间的每个位置的权值都是v,然后找长度为k的区间,使得这个区间的所有位置的权值加起来最大,输出最大权值, 所有区间不重叠 思路 ...
- Gym .102021 .German Collegiate Programming Contest (GCPC 18) (寒假gym自训第三场)
B .Battle Royale 题意:给你两个点A,B,以及一个圆S,保证两个点在圆外,且其连线与圆相交,求两点间最短距离. 思路:显然是要分别与圆相切,然后在圆弧想走,直到相交. 那么ans=与圆 ...
随机推荐
- lower()
lower() 用于把字符串中的大写字母转换成小写字母 In [1]: str = "Hello World" In [2]: str.lower() Out[2]: 'hello ...
- 第十一篇:基于TCP的一对回射客户/服务器程序及其运行过程分析( 下 )
执行分析 1. 打开服务器进程: 2. 执行netstat -a命令观察当前的连接状态: 第1条连接记录说明:绑定了本地主机的任意IP,端口为9877,目前处于监听状态. 3. 打开客户进程: 4. ...
- UML设计,可以设计程序的用例图、类图、活动图等_SurfaceView
« 对Cocos2d游戏引擎有一定的了解和实践,并接触过处理3D图形和模型库的OpenGL 在进行游戏界面的绘制工作中,需要处理大量的工作,这些工作有很多共性的操作:并且对于游戏界面的切换,元素动作的 ...
- ceph 存储安装部署
环境准备 1.三台服务器 cephnode01 192.168.254.83 cephnode02 192.168.254.84 cephnode03 192.168.254.85 2.基本环境配置 ...
- MQTT的学习研究(十五) MQTT 和android整合文章
详细参考: How to Implement Push Notifications for Android http://tokudu.com/2010/how-to-implement-push- ...
- ReactNative For Android 框架启动核心路径剖析
版权声明:本文由王少鸣原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/144 来源:腾云阁 https://www.qclo ...
- Codeforces Round #375 (Div. 2)E. One-Way Reform
题目链接:传送门 题目大意:一副无向图,要求你给边定向(变为有向图),使出度等于入度的点最多,输出有多少 个点,并且输出定向后的边(前为起点,后为终点) 题目思路:欧拉路 我们这样考虑,先考虑无向图的 ...
- Minix2.0内核源代码的组织结构
Minix2.0操作系统的源代码由两个目录组成:include/目录和src/目录 include/目录包含了操作系统所有的头文件(即.h文件) src/目录下包含了操作系统所有的源文件(.c或.s文 ...
- UUID的定义以及作用
UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OS ...
- postgresql----Btree索引
当表数据量越来越大时查询速度会下降,像课本目录一样,在表的条件字段上创建索引,查询时能够快速定位感兴趣的数据所在的位置.索引的好处主要有加速带条件的查询,删除,更新,加速JOIN操作,加速外键约束更新 ...