2021暑期牛客多校训练2

本文探讨了三个不同领域的算法问题:D-ErBaGame涉及简单的模拟和条件判断;C-DrawGrids是关于博弈论和奇偶性分析;K-Stack通过构造和栈操作解决序列问题。每个问题都展示了独特的思路和解决方案,从基础逻辑到复杂策略,适合提升编程思维。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D-Er Ba Game

在这里插入图片描述

思路:

简单的模拟,就是将各种情况判断一下,看谁的牌大并输出结果

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
const int N=2e6+5;
const int mod=1e9+7;
#define pep(i,stl) for(auto i:stl)
int arr[2005],dp[5005][5005];
ll n,m,cnt,res;
int main() {
	int t;
	cin>>t;
	while(t--) {
		int a1,b1,a2,b2;
		cin>>a1>>b1>>a2>>b2;
		if(a1>b1) swap(a1,b1);
		if(a2>b2) swap(a2,b2);
		if(a1==2&&b1==8) {
			if(a2==2&&b2==8)
				puts("tie");
			else
				puts("first");
		} else if(a1==b1) {
			if(a2==2&&b2==8)
				puts("second");
			else if(a2==b2) {
				if(a1>a2) puts("first");
				else if(a1==a2) puts("tie");
				else puts("second");
			} else
				puts("first");
		} else {
			if(a2==2&&b2==8||a2==b2)
				puts("second");
			else {
				if((a1+b1)%10>(a2+b2)%10) puts("first");
				else if((a1+b1)%10<(a2+b2)%10) puts("second");
				else {
					if(b1>b2) puts("first");
					else if(b1<b2) puts("second");
					else puts("tie");
				}
			}
		}
	}
	return 0;
}

C-Draw Grids

在这里插入图片描述

思路:

博弈论,找规律。

每个人每次只能在相邻的两点之间连线并且不能构成环,一旦所有的点都与其相邻的某个点相连则此时不管连哪两个点都会构成环,即必败点。

n个点两两相邻相连,最多有n-1个边。若n-1为奇数则先手赢,反之后手赢。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
const int N=2e6+5;
const int mod=1e9+7;
#define pep(i,stl) for(auto i:stl)
int arr[2005],dp[5005][5005];
ll n,m,cnt,res;
int main() {
	cin>>n>>m;
	if(n*m%2) puts("NO");
	else puts("YES");
	return 0;
}

K-Stack

在这里插入图片描述

思路:(思维+构造)

题目只给出了部分的b[i],对于没有给出的部分很容易想到b[i]=b[i-1]+1,即a[i]>a[i-1]。若b[i]>b[i-1]+1,则说明构造的b数组有问题,输出-1。

观察栈内的元素可以发现,越靠近栈顶的元素越后进栈。因此当b数组构造完之后,逆序遍历b[i],同时依次把1,2,3,4,5······按递增顺序放入栈里,当元素数量等于b[i]时,a[i]即为栈顶元素。最后输出a数组

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
#define fi first
#define se second
#define pb push_back
#define debug(x)   cout<<x<<endl
#define mem(a,b) memset((a),(b),sizeof(a))
const int mod=1000000007;
const double PI = acos(-1);
typedef double db;
#define pep(i,stl) for(auto i:stl)
const int N = 2e6+5;
int n,m,k,t;
int a[N];
stack<int>st;
int main() {
	cin>>n>>m;
	while(m--)
	{
		cin>>k>>t;
		a[k]=t;
	}
	rep(i,1,n){
		if(!a[i]) a[i]=a[i-1]+1;
		if(a[i]>a[i-1]+1) {
			cout<<"-1";return 0;
		}
	}
	t=1;
	pre(i,n,1){
		while(st.size()<a[i]) st.push(t++);
		a[i]=st.top();st.pop();
	}
	rep(i,1,n) cout<<a[i]<<' ';
    return 0;
}

I-Penguins

在这里插入图片描述

思路:求最短路径用bfs,为求字典序最小的路径在对某个状态搜索时按D,L,R,U的顺序搜;

用四位数组来标记已经搜过的状态,若该状态已搜过则直接跳过。

搜索时需要注意两只企鹅会出现一只动,一只不动的情况。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
#define fi first
#define se second
#define pb push_back
#define debug(x)   cout<<x<<endl
#define mem(a,b) memset((a),(b),sizeof(a))
const int mod=1000000007;
const double PI = acos(-1);
typedef double db;
#define pep(i,stl) for(auto i:stl)
const int N = 2e6+5;
int n,m,k,mi=INF;
int t,dx1[]={1,0,0,-1},dy1[]={0,-1,1,0},dx2[]={1,0,0,-1},dy2[]={0,1,-1,0};
string di[4]={"D","L","R","U"};
struct 	p{
	int st,x1,y1,x2,y2;
	string s;
};
int mp[25][25][25][25]; 
string ans;
queue<p>q;
string a[25],b[25];
void bfs(){
	p tem={0,19,19,19,0,""};
	q.push(tem);
	while(q.size()){
		tem=q.front();q.pop();
		if(tem.x1==0&&tem.y1==19&&tem.x2==0&&tem.y2==0)
		{
			if(mi>tem.st) mi=tem.st,ans=tem.s;
			return; 
		}
		if(tem.st>=mi) continue;
		if(mp[tem.x1][tem.y1][tem.x2][tem.y2]) continue;
		else mp[tem.x1][tem.y1][tem.x2][tem.y2]=1;
		int x1=tem.x1,y1=tem.y1,x2=tem.x2,y2=tem.y2;
		rep(i,0,3){
				int x=x1,y=y1,x0=x2,y0=y2;
				if(x1+dx1[i]>=0&&x1+dx1[i]<20&&y1+dy1[i]>=0&&y1+dy1[i]<20&&a[x1+dx1[i]][y1+dy1[i]]!='#')
				x+=dx1[i],y+=dy1[i];
				if(x2+dx2[i]>=0&&x2+dx2[i]<20&&y2+dy2[i]>=0&&y2+dy2[i]<20&&b[x2+dx2[i]][y2+dy2[i]]!='#')
				x0+=dx2[i],y0+=dy2[i];
				q.push(p{tem.st+1,x,y,x0,y0,tem.s+di[i]});
		}
	}
}
void fun(){
	int x1=19,y1=19,x2=19,y2=0;
	a[x1][y1]='A';b[x2][y2]='A';
	rep1(i,0,ans.size()){
		switch(ans[i]){
			case 'D':if(x1+1>=0&&x1+1<20&&a[x1+1][y1]!='#')a[++x1][y1]='A';if(x2+1>=0&&x2+1<20&&b[x2+1][y2]!='#')b[++x2][y2]='A';break;
			case 'L':if(y1-1>=0&&y1-1<20&&a[x1][y1-1]!='#')a[x1][--y1]='A';if(y2+1>=0&&y2+1<20&&b[x2][y2+1]!='#')b[x2][++y2]='A';break;
			case 'R':if(y1+1>=0&&y1+1<20&&a[x1][y1+1]!='#')a[x1][++y1]='A';if(y2-1>=0&&y2-1<20&&b[x2][y2-1]!='#')b[x2][--y2]='A';break;
			case 'U':if(x1-1>=0&&x1-1<20&&a[x1-1][y1]!='#')a[--x1][y1]='A';if(x2-1>=0&&x2-1<20&&b[x2-1][y2]!='#')b[--x2][y2]='A';break;
		}
	}
}
int main() {
	rep1(i,0,20)
	cin>>a[i]>>b[i];
	bfs();
	cout<<mi<<endl<<ans<<endl;
	fun();
	rep1(i,0,20)
	cout<<a[i]<<' '<<b[i]<<endl;
    return 0;
}

F-Girlfriend

在这里插入图片描述

思路:计算几何

∣ A P 1 ∣ > = k 1 ∣ B P 1 ∣ |AP_1|>=k_1|BP_1| AP1>=k1BP1

∣ A P 1 ∣ 2 > = k 1 2 ∣ B P 1 ∣ 2 |AP_1|^2>=k1^2|BP_1|^2 AP12>=k12BP12

( x − x 1 ) 2 + ( y − y 1 ) 2 + ( z − z 1 ) 2 > = k 1 2 [ ( x − x 2 ) 2 + ( y − y 2 ) 2 + ( z − z 2 ) 2 ] (x-x_1)^2+(y-y1)^2+(z-z_1)^2>=k_1^2[(x-x_2)^2+(y-y2)^2+(z-z_2)^2] (xx1)2+(yy1)2+(zz1)2>=k12[(xx2)2+(yy2)2+(zz2)2]

( k 1 2 − 1 ) ( x 2 + y 2 + c 2 ) − ( 2 k 1 2 x 2 − 2 x 1 ) x − ( 2 k 1 2 y 2 − 2 y 1 ) y − ( 2 k 1 2 z 2 − 2 z 1 ) z + k 1 2 ( x 2 2 + y 2 2 + z 2 2 ) − x 1 2 − y 1 2 − z 1 2 < = 0 (k1^2-1)(x^2+y^2+c^2)-(2k_1^2x_2-2x_1)x-(2k_1^2y_2-2y_1)y-(2k_1^2z_2-2z_1)z+k_1^2(x_2^2+y_2^2+z_2^2)-x_1^2-y_1^2-z_1^2<=0 (k121)(x2+y2+c2)(2k12x22x1)x(2k12y22y1)y(2k12z22z1)z+k12(x22+y22+z22)x12y12z12<=0

由上式可知: p 1 p_1 p1的活动范围为一个球体的体积

因此问题即为球两个球体相交部分的体积

参考链接

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
#define mem(a,b) memset((a),(b),sizeof(a))
const int N=2e6+5;
const int mod=1e9+7;
const double PI = acos(-1);
#define pep(i,stl) for(auto i:stl)
multiset<int>s;
bool b[105];
int main() {
	int t;
	cin>>t;
	double ans=0;
	while(t--){
		double x1,x2,x3,x4,y1,y2,y3,y4,z1,z2,z3,z4,k1,k2;
		cin>>x1>>y1>>z1>>x2>>y2>>z2>>x3>>y3>>z3>>x4>>y4>>z4>>k1>>k2;
		double kx1=k1*k1-1,kx2=k2*k2-1;
		double ax1=k1*k1*x2-x1,by1=k1*k1*y2-y1,cz1=k1*k1*z2-z1;
		double ax2=k2*k2*x4-x3,by2=k2*k2*y4-y3,cz2=k2*k2*z4-z3;
		ax1/=kx1;ax2/=kx2;by1/=kx1;by2/=kx2;cz1/=kx1;cz2/=kx2;
		double d1=k1*k1*(x2*x2+y2*y2+z2*z2)-x1*x1-y1*y1-z1*z1;
		double d2=k2*k2*(x4*x4+y4*y4+z4*z4)-x3*x3-y3*y3-z3*z3;
		d1/=kx1;d2/=kx2; 
		double r1=sqrt(ax1*ax1+by1*by1+cz1*cz1-d1);
		double r2=sqrt(ax2*ax2+by2*by2+cz2*cz2-d2);
		double d=sqrt((ax2-ax1)*(ax2-ax1)+(by2-by1)*(by2-by1)+(cz2-cz1)*(cz2-cz1));
		if(d>=r1+r2) ans=0;
		else if(d<=r2-r1) ans=4.0/3.0*PI*r1*r1*r1;
		else if(d<=r1-r2) ans=4.0/3.0*PI*r2*r2*r2;
		else{
			double h1=r1*(1.0-(r1*r1+d*d-r2*r2)/(2.0*r1*d)),h2=r2*(1.0-(r2*r2+d*d-r1*r1)/(2.0*r2*d));
			ans=PI/3.0*((3.0*r1-h1)*h1*h1+(3.0*r2-h2)*h2*h2);	
		}  
		printf("%.3f\n",ans);
	} 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值