牛客国庆集训派对Day1(A C E L)

25 篇文章 0 订阅
4 篇文章 0 订阅

链接: https://www.nowcoder.com/acm/contest/201#question

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)=p2x2+p1x+q2y2+q1y a x + b y = c ax + by = c ax+by=c 有整数解的条件下的最小值。
思路: 显然 y = c − a x b y = \frac{c-ax} b y=bcax, 这样 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+b2a2q2)b22acq2baq1+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 ] &lt; = m d[i]-d[i-1] &lt;= m d[i]d[i1]<=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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牛客 a卷2022年第四季度的华为目中,要求考生设计一种高效的数据结构,能够支持以下几种操作: 1. 添加一个元素 2. 删除一个元素 3. 查找是否存在某个元素 4. 返回元素的总数 该数据结构要求满足空间复杂度较小、时间复杂度较低、能够快速地进行查找和修改等多种操作。 想要编写这样一种数据结构,我们可以参考许多已有的经典算法与数据结构,如二叉树、哈希表、红黑树等,通过综合利用它们的优点来实现这个问的解决。 例如,我们可以通过哈希表来存储所有元素的值,并在每个哈希链表的元素中再使用红黑树来进行排序与查找。这样,我们既能够轻松地进行元素的添加和删除操作,也能够在查找较大数据范围和数量时保持较高的速度与效率。同时,由于使用了多个数据结构来协同完成这个问,我们也能够在空间复杂度上适度地进行优化。 当然,在具体设计这个数据结构的过程中,我们还需要考虑一些实践中的细节问,例如如何避免哈希冲突、如何处理数据丢失与被删除元素所占用的空间等问,这都需要相应的算法与流程来进行处理。 总体来看,设计这种支持多种操作的高效数据结构,需要我们具备丰富的算法知识和编程实践能力,同时需要我们在具体处理问时能够将多种算法和数据结构进行有效地结合。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值