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=与圆 ...
随机推荐
- DOCKER在windows上安装与配置
1.下载程序 安装包 https://github.com/boot2docker/windows-installer/releases(这个地址国内下载很慢) 用这个: https://get.da ...
- select下拉框不能赋值
前言: 需要用到类似于下面的下拉选择框,按照官方文档写,始终实现不了下拉框赋上值的情况. 过程: 认认真真的看了好几遍文档,但是还没找到原因,不过还是应该感谢自己加入的vue-admin的微信群,大家 ...
- React如何进行事件传参
今天在学习React的es6语法的时候,发现了个有趣的现象,就是this的指向问题.es6的this不同于es5,它在创立函数伊始便已经存在了,而不是像es5一样,睡调用的函数,this指向谁.但是这 ...
- poj_1151 线段树
题目大意 在平面上给定n个矩形,可以相互覆盖全部或者部分,求出矩形占据的总面积. 题目分析 将矩形按照x方向的进行分割之后,将平面沿着y方向划分一系列单元(不定高度),每个矩形在y方向上占据若干连续的 ...
- 索引原理 B tree
数据库原理之-索引 背景介绍: 用数据库的时候经常有几个疑问: 1:为啥通过加索引就能提升数据的查询料率? 2:为啥加多了索引会导致增删改的效率变低? 3:为啥有的人能用好有的人用不好? 这些问题我们 ...
- 微信小程序5.2.2版本,找不着resource下exml皮肤
问题描述: egret engine 5.2.2 原来5.1.11好好的,一升级就跪了 新建一个项目,找不到皮肤... 已发到论坛问去了,现在只能手动复制皮肤到小游戏目录下... 解决方案: 卸载重新 ...
- 【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP
[BZOJ5109][CodePlus 2017]大吉大利,晚上吃鸡! Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏 ...
- 几行小代码,将Testlink的xml用例导入至excel
最近在使用Testlink时,发现导入的用例是xml格式,且没有合适的工具转成excel格式,xml使用excel打开显示的东西也太多,网上也有相关工具转成csv格式的,结果也不合人意. 那求人不如尔 ...
- Android动态加载ListView中的Item
我这周上网看到动态增加listview的每一项item的布局,今天抽空自己写了一个,方便自己日后使用,这个效果还是很不错的,用到了Adapter的notifyDataSetChanged()方法,当点 ...
- 一致性哈希算法(consistent hashing)(转)
http://blog.csdn.net/cywosp/article/details/23397179