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=与圆 ...
随机推荐
- mysql 小数处理
1)四舍五入,保留小数 使用ROUND函数(注意不要使用FORMAT函数,FORMAT函数返回值带有逗号,赋值时会出现错误) 示例:保留两位小数 ROUND(price,2) 2)向上取整 CEIL ...
- ActiveMQ伪集群部署
本文借鉴http://www.cnblogs.com/guozhen/p/5984915.html,在此基础上进行了完善,使之成为一个完整版的伪分布式部署说明,在此记录一下! 一.本文目的 介绍如何在 ...
- Mysql全文搜索match against的用法
全文检索在 MySQL 中就是一个 FULLTEXT 类型索引.FULLTEXT 索引用于 MyISAM 表,可以在 CREATE TABLE 时或之后使用 ALTER TABLE 或 CREATE ...
- Android AndroidManifest.xml配置文件
AndroidManifest.xml配置文件介绍本质:AndroidManifest.xml是整个应用的主配置清单文件.包含:该应用的包名.版本号.组件.权限等信息.作用:记录该应用的相关配置信息. ...
- ubuntu下Eclipse创建Django项目
(注:部分过程可能需要FQ) Eclipse版本:Mars.x 点击help->Eclipse Marketplace,搜索“PyDev”并下载安装. 然后选择window->prefer ...
- 百度地图地址查询API使用
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgsAAALxCAIAAABdNHLmAAAgAElEQVR4nOy9/VMbZ5rvnf/hbM7zy3 ...
- Android英文文档翻译系列(2)——HandlerThread
public class HandlerThread extends Thread Class Overview Handy class for starting a new threa ...
- c++11——move/forward
std::move c++11中提供了std::move()来将左值转换为右值,从而方便的使用移动语义.move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存拷贝. c ...
- BNU4208:Bubble sort
冒泡排序(BubbleSort)的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面.即首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将小数放前,大数放后,如 ...
- java基础---->数字签名算法的介绍
数字签名(又称公钥数字签名)是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法.关于数字签名的介绍,可以参见百度百科:http://baike.baidu.c ...