链接: https://www.nowcoder.com/acm/contest/201#question
牛客国庆集训派对Day1
A. Tobaku Mokushiroku Kaiji(水题)
题意: 给出剪刀石头布卡牌的数量,问其中一个人最多能赢多少次。
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char const *argv[])
{
int a, b, c, d, e, f, ans = 0;
cin>>a>>b>>c>>d>>e>>f;
if(a > e) ans += e;
else ans += a;
if(b > f) ans += f;
else ans += b;
if(c > d) ans += d;
else ans += c;
cout<<ans<<endl;
return 0;
}
C. Utawarerumono(数学)
题意: 求表达式
f
(
x
,
y
)
=
p
2
∗
x
2
+
p
1
∗
x
+
q
2
∗
y
2
+
q
1
∗
y
f(x, y) = p_2*x^2 + p_1*x + q_2*y^2 + q1*y
f(x,y)=p2∗x2+p1∗x+q2∗y2+q1∗y 在
a
x
+
b
y
=
c
ax + by = c
ax+by=c 有整数解的条件下的最小值。
思路: 显然
y
=
c
−
a
x
b
y = \frac{c-ax} b
y=bc−ax, 这样
f
f
f 就只含
x
x
x 一个变量。一元二次函数求最小值就很容易了, 简单推一下, 就知道最小的取值的
x
=
−
−
2
∗
a
∗
c
∗
q
2
b
2
−
a
∗
q
1
b
+
p
1
2
∗
(
p
2
+
a
2
∗
q
2
b
2
)
x = -\frac{-\frac {2*a*c*q2} {b^2} - \frac{a*q1} b + p1} {2 * (p2 + \frac{a^2*q2} {b^2})}
x=−2∗(p2+b2a2∗q2)−b22∗a∗c∗q2−ba∗q1+p1 , 然后分别向左,向右找第一个符合条件的
y
y
y ,最后输出两者之中
f
f
f 的最小值。
(比赛的时候是用参数方程的形式写的,但是不知道为什么WA,对拍也出不来。后来只能换一种写法。)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a, b, c, p1, p2, q1, q2, ans;
LL f(LL x, LL y) {
return p2*x*x+p1*x+q2*y*y+q1*y;
}
int main(){
cin>>a>>b>>c>>p1>>p2>>q1>>q2;
if (a == 0 && b == 0 && c == 0) {
cout<<0<<endl;
}
else if (a == 0 && b == 0) {
puts("Kuon");
}
else if (c % __gcd(a, b) != 0) {
puts("Kuon");
}
else if (b == 0) {
if (c % a != 0) {
puts("Kuon");
}
else {
LL x = c / a;
ans = p2 * x * x + p1 * x;
cout<<ans<<endl;
}
}
else if (a == 0) {
if (c % b != 0) {
puts("Kuon");
}
else {
LL y = c / b;
ans = q2 * y * y + q1 * y;
cout<<ans<<endl;
}
}
else{
LL x = -( (-(2*a*c*q2)/(b*b) - (a*q1/b) + p1) / (2* (p2 + (a*a*q2)/b*b) ) );
LL xl = x, xr = x;
while((c-a*xl)%b) xl--;
while((c-a*xr)%b) xr++;
LL yl = (c-a*xl)/b;
LL yr = (c-a*xr)/b;
cout<<min(f(xl, yl), f(xr, yr))<<endl;
}
return 0;
}
E. Eustia of the Tarnished Wings(水题)
题意 : 给你
n
n
n 个数,其中两个数绝对值之差小于等于
m
m
m 的可以合并,合并后的数可以是两个数的任意一个,问最后能剩下多少个数。
思路: 排序,然后扫一遍,不符合条件
d
[
i
]
−
d
[
i
−
1
]
<
=
m
d[i]-d[i-1] <= m
d[i]−d[i−1]<=m 就结果加一。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000100;
int n, m, d[MAXN];
int main(int argc, char const *argv[])
{
cin>>n>>m;
for (int i = 0; i < n; ++i) {
cin>>d[i];
}
sort(d, d+n);
int cnt = 1;
for (int i = 1; i < n; ++i) {
if(d[i] - d[i-1] > m) cnt++;
}
cout<<cnt<<endl;
return 0;
}
L. New Game!(最短路)
题意: 平面直角坐标系上有两条直线
L
1
,
L
2
L_1, L_2
L1,L2,和
n
n
n 个圆, 在两条直线上,圆上和圆内走花费为
0
0
0, 其他为欧式距离。问从
L
1
L_1
L1 到
L
2
L_2
L2 的最小花费是多少。
思路: 将两条直线和圆都看成是图上的点,边权是两个图形想要到达的最小花费,将每两个图形之间建边,跑一遍最短路就行了。(注意边权是浮点型)
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1100;
const double DMAX = 1000000000;
struct edge {
int to;
double cost;
bool operator < (const edge & d) const {
return cost < d.cost;
}
};
std::vector<edge> E[MAXN];
void add_edge(int u, int v, double c) {
E[u].push_back((edge){v, c});
}
double dist[MAXN];
void dijkstra(int s) {
// memset(dist, DMAX, sizeof(dist)); // error
// cout<<"dist : "<<endl;
for (int i = 0; i < MAXN; ++i) {
dist[i] = DMAX;
// cout<<dist[i]<<endl;
}//cout<<endl;
priority_queue<edge > pq;
dist[s] = 0;
pq.push((edge){s, dist[s]});
while(!pq.empty()) {
int now = pq.top().to;
pq.pop();
for (int i = 0; i < E[now].size(); ++i) {
int v = E[now][i].to;
if(dist[v] > dist[now] + E[now][i].cost) {
dist[v] = dist[now] + E[now][i].cost;
pq.push((edge){v, dist[v]});
// cout<<"push : "<<v<<" "<<dist[v]<<endl;
}
}
}
}
int main(int argc, char const *argv[])
{
int n;
double A, B, C1, C2, x[MAXN], y[MAXN], r[MAXN];
cin>>n>>A>>B>>C1>>C2;
for (int i = 1; i <= n; ++i) {
cin>>x[i]>>y[i]>>r[i];
}
double sq = sqrt(A*A+B*B);
double d = abs(C1-C2)/sq;
add_edge(0, n+1, d);
add_edge(n+1, 0, d);
for (int i = 1; i <= n; ++i) {
d = max(0.0, abs(A*x[i] + B*y[i] + C1)/sq-r[i]);
add_edge(0, i, d);
add_edge(i, 0, d);
}
for (int i = 1; i <= n; ++i) {
d = max(0.0, abs(A*x[i] + B*y[i] + C2)/sq-r[i]);
add_edge(n+1, i, d);
add_edge(i, n+1, d);
}
for (int i = 1; i <= n; ++i) {
for (int j = i+1; j <= n; ++j) {
d = max(0.0, sqrt(pow((x[i]-x[j]), 2) + pow((y[i]-y[j]), 2))-(r[i]+r[j]));
add_edge(i, j, d);
add_edge(j, i, d);
}
}
/*for (int i = 0; i <= n+1; ++i) {
for (int j = 0; j < E[i].size(); ++j) {
cout<<E[i][j].to<<","<<E[i][j].cost<<" ";
}cout<<endl;
}*/
dijkstra(0);
cout<<dist[n+1]<<endl;
return 0;
}