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=与圆 ...
随机推荐
- Oracle-未能加载文件或程序集“oracle.dataaccess”或它的某一个依赖项。试图加载格式不正确的程序。
未能加载文件或程序集“oracle.dataaccess”或它的某一个依赖项.试图加载格式不正确的程序. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以 ...
- img-图片二进制流 64位前端显示
碰到的场景:因为使用iframe子窗口打开,多张的二维码图片创建方法调用,导致页面打开缓慢, 所以将调取方式转换成<img src="data:image/png;base64,@it ...
- MQTT协议笔记之订阅
前言 记忆不太好的时候,只能翻看以前的文章/笔记重新温习一遍,但找不到MQTT协议有关订阅部分的描述,好不容易从Evernote中找到贴出来,这样整个MQTT协议笔记,就比较齐全了. SUBSCRIB ...
- wamp安装和基础配置
一 下载地址 二 安装 三 修改默认网站目录 四 修改数据库密码 一 下载地址 wamp百度软件中心 wamp官方下载地址 二 安装 windows环境下wampserver的配置教程——超级详细 w ...
- c# Winform间的页面传值
Form2 public partial class Form2 : Form { public string str; public Form2() { InitializeComponent(); ...
- JS实现拖拽效果
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...
- javascript飞机大战-----006创建敌机
先写一个敌机类 /* 创建敌机: */ function Enemy(blood,speed,imgs){ //敌机left this.left = 0; //敌机top this.top = 0; ...
- tomcat启动时常见错误问题集锦
1:环境变量 问题:The JAVA_HOME environment variable is not defined This environment variable is needed to r ...
- 麦子学院bootstrap实战项目官网,后台,jquery.singlePageNav.min.js ,wow.min.js,animate.css使用
1.源码笔记 我的源码+笔记(很重要):链接: https://pan.baidu.com/s/1eSxgLV0 密码: 2pi2 感谢麦子学院项目相关视频:链接: https://pan.baidu ...
- 徐州网络赛F-Feature Trace【暴力】
Morgana is learning computer vision, and he likes cats, too. One day he wants to find the cat moveme ...