The 2024 Sichuan Provincial Collegiate Programming Contest——F、H

B. Link Summon

 题解链接

B题题解来说是道贪心,但我不知道为什么像题解那样贪心,有知道的大佬可以说一说。。。

F. Isoball: 2D Version

F题是道比较直观的平面几何题。因为小球直径是r所以将矩形各个边向中间缩小r形成一个小矩形,如果圆心可能落在小矩形上(包括边界)那么输出yes,否则no。这就是先对于矩形的处理。

对于这道题有两种判断方法来确定小球是否能落在小矩形内

第一种就是比较板子的,判断圆心移动路径(为射线)与矩形的边(或者对角线)是否有交点,这种方法我不太会。。。就在这里没有写,大家可以看看cf大佬写的代码。

第二种比较傻的方法,就是判断小球的圆心到达小矩形的左边的情况下,计算对应的时间,以此计算y的位置,判断y是否合法,合法的话输出yes;

然后再判断小球的圆心到达小矩形的右边情况下,计算对应的时间,以此计算y的位置,判断y是否合法,合法的话输出yes;

然后再判断小球的圆心到达小矩形的下边的情况下,计算对应的时间,以此计算x的位置,判断是否合法,合法的话输出yes;

最后判断小球的圆心到达小矩形的上边的情况下,计算对应的时间,以此计算x的位置,判断是否合法,合法的话输出yes;

如果上述情况都不成立的话输出no。

这种方法的坑点(卡了我一天。。。)就是需要注意圆心是否朝小矩形的各个边移动,这点必须要判断,不能忽视,我是看了大佬的代码才注意到的。。。具体可以看我的判断条件。

还有就是小矩形可能根本不存在,这是样例2,需要判断一下。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

void slove(){
    ll x, y, r, vx, vy, lx, ly, rx, ry;
    double time;
    scanf("%lld %lld %lld %lld %lld", &x, &y, &r, &vx, &vy);
    scanf("%lld %lld %lld %lld", &lx, &ly, &rx, &ry);
    lx += r, ly += r, rx -= r, ry -= r;
	if(lx <= rx && ly <= ry){
		if(x >= lx && x <= rx){
			if(y >= ly && y <= ry){
				printf("Yes\n");
				return ;
			}
		}
		if(vx != 0){
			double xx, yy;
			if((x <= lx && vx > 0) || (x >= lx && vx < 0)){
				time = (double)(lx - x) / vx;
				yy = y + vy * time;
				if((lx - x) * vx >= 0 && yy <= ry && yy >= ly){
					printf("Yes\n");
					return ;
				}
			}
			if((x <= rx && vx > 0) || (x >= rx && vx < 0)){
				time = (double)(rx - x) / vx;
				yy = y + vy * time;
				if((rx - x) * vx >= 0 && yy <= ry && yy >= ly){
					printf("Yes\n");
					return ;
				}
			}
		}
		if(vy != 0){
			double xx, yy;
			if((y <= ly && vy > 0) || (y >= ly && vy < 0)){
				time = (double)(ly - y) / vy;
				xx = x + vx * time;
				if((ly - y) * vy >= 0 && xx <= rx && xx >= lx){
					printf("Yes\n");
					return ;
				}
			}
			if((y <= ry && vy > 0) || (y >= ry && vy < 0)){
				time = (double)(ry - y) / vy;
				xx = x + vx * time;
				if((ry - y) * vy >= 0 && xx <= rx && xx >= lx){
					printf("Yes\n");
					return ;
				}
			}
		}
	}
	printf("No\n");
	return ;
}
int main(){
    ll t;
    scanf("%lld", &t);
    while(t--){
        slove();
    }
    return 0;
}

大佬的代码写的太牛了,思想都差不多,我就一起粘再这里了(卡的点也是看大佬代码才知道的。。。)

266388810 xinglili

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
 
int t,rx,ry,r,vx,vy,a,b,c,d;
 
signed main()
{
	cin>>t;
	while(t--)
	{
		cin>>rx>>ry>>r>>vx>>vy>>a>>b>>c>>d;
		a+=r,b+=r,c-=r,d-=r;
		
		int flag=0;
		if(a<=c && b<=d)
		{
			double s1=(double)(a-rx)*vy/vx,s2=(double)(c-rx)*vy/vx;
			double s3=(double)(b-ry)*vx/vy,s4=(double)(d-ry)*vx/vy;
			
			if((a-rx)*vx>=0 && ry+s1>=b && ry+s1<=d)flag=1;
			if((c-rx)*vx>=0 && ry+s2>=b && ry+s2<=d)flag=1;
			if((b-ry)*vy>=0 && rx+s3>=a && rx+s3<=c)flag=1;
			if((d-ry)*vy>=0 && rx+s4>=a && rx+s4<=c)flag=1;
		}
		
		if(flag)cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
 
	return 0;	
}

有时间要看看平面几何了,感觉题比较直观,但写起来会出现小错,很隐蔽的小错,其实我也写了一版第一种方法的代码,但一直wa3,就是不知道哪里错了

H. GG and YY's Stone Game

一道博弈题,打表发现规律:

石子数123456
GG输赢winwinlosewinwinlose

所以GG的输赢和n%3有关,对于赢的人获得的石子数,题目说明两人都会尽可能获得更多的石子,所以当n处于3的倍数时,YY会赢,但GG每次都会拿尽可能多的石子(即2个石子),为了保证赢的状态,YY每次只会拿一个石子,所以YY拿的石子数为n/3,当n%3!=0时,GG先拿1或2个石子使石子数到达必输态来交给YY处理,YY会拿尽可能多的石子(即2个石子)(这种情况就像是n为3的倍数一样),那么GG每次就只能拿一个石子,这样的话GG拿的石子总数就是n/3 + n%3

#include<bits/stdc++.h>
#define ll long long
#define inf 1e9
using namespace std;


void slove(){
    ll n;
    cin >> n;
    if(n % 3){
        cout << 0 << " " << n / 3 + n % 3 << endl;
    }
    else{
        cout << 1 << " " << n / 3 << endl;
    }
}
int main(){
    ll t;
    cin >> t;
    while(t--){
        slove();
    }
    return 0;
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值