牛客周赛 Round 55

牛客周赛 Round 55

A 小红的字符串

链接:https://ac.nowcoder.com/acm/contest/87656/A
来源:牛客网

题目描述

小红拿到了一个长度为 3 且仅由小写字母组成的字符串,她每次操作可以修改任意一个字符,小红希望最终所有字符都相同。 
你能帮小红求出最小的操作次数吗?

输入描述:

第一行输入一个长度为 3 且仅由小写字母组成的字符串 𝑠。

输出描述:

在一行上输出一个整数,表示最小的操作次数。

示例1

输入
aba
输出
1

说明

操作 1 次,将第二个字符修改为 ‘𝑎’ 即可。

示例2

输入
uuu
输出
0

题解

不解释,怎么做都能做出来

#include<bits/stdc++.h>
using namespace std;
string s;int a[30];
int main(){
    int i,j,k;
    cin>>s;
    for(i=0;i<3;i++)
        a[s[i]-'a']=1;
    int sum=0;
    for(i=0;i<26;i++)
        sum+=a[i];
    printf("%d\n",sum-1);
    return 0;
}
B 小红的序列乘积

链接:https://ac.nowcoder.com/acm/contest/87656/B
来源:牛客网

题目描述

小红有一个长度为 𝑛 的整数序列 {𝑎1,𝑎2,…,𝑎𝑛},定义 𝑓𝑖=𝑎1×𝑎2×⋯×𝑎𝑖 ,即前 𝑖 项的乘积。现在小红想知道 𝑓1,𝑓2,…,𝑓𝑛 中,有多少个数的个位数是 6 。

输入描述:

第一行输入一个整数 𝑛(1≤𝑛≤105) 代表序列中元素的数量。
第二行输入 𝑛 个整数 𝑎1,𝑎2,⋯ ,𝑎𝑛(1≤𝑎𝑖≤109) 代表序列元素。

输出描述

在一行上输出一个整数,代表 𝑓1,𝑓2,⋯ ,𝑓𝑛 中,个位数是 6 的数的个数。

示例1

输入
5
1 2 3 4 4
输出
2

说明

𝑓 = [1,2,6,24,96],有 2 个数的个位数是 6。

示例2

输入
6
1 1 4 5 1 4
输出
0

题解

保留最后一位就行

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

#define int long long 
int n,a[100005],ans,sum=1;
signed main(){
    int i,j,k;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i];
        sum=sum*a[i]%10;
        if(sum==6)ans++;
    }
    cout<<ans<<endl;
    return 0;
}
C 小红的数组重排

链接:https://ac.nowcoder.com/acm/contest/87656/C
来源:牛客网

题目描述

给出一个数字 𝑛 和一个长度为 𝑛 的数组 [𝑎1,𝑎2,…,𝑎𝑛] 。现在你可以以任意方式重新排列数组 𝑎,问是否存在重排后的数组 𝑎 满足:𝑎1×𝑎2<𝑎2×𝑎3<⋯<𝑎𝑛−1×𝑎𝑛。

输入描述:

第一行输入一个整数𝑛(3≤𝑛≤5×105) 代表数组中的元素数量。
第二行输入 𝑛 个整数 𝑎1,𝑎2,⋯ ,𝑎𝑛(0≤𝑎𝑖≤109) 代表数组元素。

输出描述:

若存在符合题意的排列后的数组 𝑎,在一行上输出 YES ,随后在第二行上输出这个数组;否则,直接输出 NO 。
如果存在多个解决方案,您可以输出任意一个。

示例1

输入
4
7 2 5 1
输出
YES
1 5 2 7

说明

重排后满足:1×5<5×2<2×7 。

示例2

输入
6
1 1 4 5 1 4
输出
NO

题解

不得不说这道题有点坑人
分析题目 要求:a1<a3<a5 … < a 2n-1 a2<a4<a6…<a 2n
抛开别的不谈,如果能成功,你按照升序输出不就行了吗
然后考虑不成功的情况:一个数出现了3次一定不成功,因为会出现相等的情况
然后这个我当时没想出来:出现0的次数不能2次!!!【原因显而易见了,不解释】

#include<bits/stdc++.h>
using namespace std;
int n,a[500005];
int main(){
    int i,j,k;
    cin>>n;
    for(i=1;i<=n;i++)
        cin>>a[i];
    sort(a+1,a+1+n);
    bool flag=1;
    for(i=1;i<=n;i++){
        for(j=i;a[j]==a[i];j++);
        int sum=j-i;
        if(sum>=3){
            printf("NO\n");
            return 0;
        }
    }
    if(a[1]==0&&a[2]==0){
        printf("NO\n");
        return 0;
    }
    printf("YES\n");
    for(i=1;i<=n;i++)
        printf("%d ",a[i]);
    printf("\n");
    return 0;
}

/*
a1<a3<a5<a7....
a2<a4<a6<a8....
1 1 2 2 3 3 4 4 5 5 

*/
D 虫洞操纵者

链接:https://ac.nowcoder.com/acm/contest/87656/D
来源:牛客网

题目描述

你需要在一个可以上下左右移动的 𝑛×𝑛 棋盘上解开一个迷宫:棋盘四周都是墙;每个方格要么是可以通过的空方格 ′0′ ,要么是不可通过的墙方格 ′1′ ;你可以沿着空方格通行;你已经被传送到了迷宫的左上角(第 1 行第 1 列的位置),你知道终点位于迷宫右下角(第
𝑛 行第 𝑛 列的位置)。
别人都不知道的是,你是一个虫洞大师,当你所在的位置能同时看到左右两侧或上下两侧最近的那两面相对的墙时,你可以在这两面墙上开启虫洞,靠近后从一侧进入,穿越它到达另一侧。
现在,你准备好以最短的步数离开迷宫了吗!

输入描述:

第一行输入一个整数 𝑛(2≤𝑛≤103) 代表迷宫的大小。
此后 𝑛 行,第 𝑖 行输入 𝑛 个整数𝑎𝑖,1,𝑎𝑖,2,…,𝑎𝑖,𝑛(0≤𝑎𝑖,𝑗≤1) 代表迷宫中第 𝑖 行第 𝑗 列这个格子中的情况,其中 0 代表空方格,1 代表墙方格。保证起点和终点不为墙壁。

输出描述:

在一行上输出一个整数,代表离开迷宫需要的最短步数,如果无论如何都无法离开迷宫,则直接输出 −1 。

示例1

输入
5
0 0 0 1 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0
1 0 0 0 0
输出
3

说明

该样例示意图如下图所示。全部墙壁的位置都使用粗黑线标注。先从 (1,1) 向右移动一步走到 (1,2) ,此时可以开启一个虫洞(使用紫色箭头标注),向上移动一步到达 (5,2) ;此时可以开启第二个虫洞(使用红色箭头标注),向左移动一步到达 (5,5) 。在这里插入图片描述

注意,在该样例中,不能直接从 (1,1) 开启虫洞(使用黑色箭头标注)到达 (1,5) ,因为 (1,4) 存在两面墙遮挡了视线;不能直接从 (4,3) 开启虫洞(使用绿色箭头标注)到达 (1,3) ,因为这两面墙不是相对的。
在这里插入图片描述

示例2

输入
5
0 0 0 1 0
1 1 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0
输出
5

说明

在这里插入图片描述

示例3

输入
2
0 1
1 0
输出
-1

题解

就是将两个靠近墙的点进行连边,剩下的bfs。
理论是这样,但是真的很难写啊
在这里插入图片描述
大佬的代码,写不出来 qwq

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

#define x first
#define y second

using namespace std;

typedef pair<int,int>PII;

const int N = 3e6+10,M = 4*N,S=1e3+10;

int e[M],ne[M],h[N],idx;
bool st[N];
int n;
int dist[N];
int w[S][S];
queue<int>q;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int pre[S][S],up[S][S];

int get(int x,int y){
    return (x-1)*n+y;
}

void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

int bfs(){
    
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    
    q.push(1);
    
    
    while(q.size()){
        int ver=q.front();
        q.pop();
        
        for(int i=h[ver];~i;i=ne[i]){
            int j=e[i];
            if(dist[j]>dist[ver]+1){
                dist[j]=dist[ver]+1;
                q.push(j);
                // cout<<(j-1)/n+1<<' '<<(j-1)%n+1<<endl;
            }
        }
    }
    return dist[n*n];
}

int main(){
    cin>>n;
    
    for(int i=0;i<=n+5;i++){
        for(int j=0;j<=n+5;j++){
            w[i][j]=1;
        }
    }
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>w[i][j];
        }
    }
    
    memset(h,-1,sizeof h);
    
    for(int i=1;i<=n+1;i++){
        for(int j=1;j<=n+1;j++){
            if(w[i][j]==1){
                pre[i][j]=j;
            }else{
                pre[i][j]=pre[i][j-1];
            }
        }
    }
    
    for(int j=1;j<=n+1;j++){
        for(int i=1;i<=n+1;i++){
            if(w[i][j]==1){
                up[i][j]=i;
            }else{
                up[i][j]=up[i-1][j];
            }
        }
    }
    
    
    for(int i=1;i<=n+1;i++){
        for(int j=1;j<=n+1;j++){
            if(i==n+1&&j==n+1)continue;
            if(w[i][j]==1){
                if(j>=2&&w[i][j-1]==0){
                    add(get(i,j-1),get(i,pre[i][j-1]+1));
                    add(get(i,pre[i][j-1]+1),get(i,j-1));
                }
                if(i>=2&&w[i-1][j]==0){
                    add(get(i-1,j),get(up[i-1][j]+1,j));
                    add(get(up[i-1][j]+1,j),get(i-1,j));
                }
            }
        }
    }
    
    
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(w[i][j]==0){
                for(int k=0;k<4;k++){
                    int a=dx[k]+i,b=dy[k]+j;
                    if(a<1||b<1||a>n||b>n||w[a][b]==1)continue;
                    add(get(i,j),get(a,b));
                    add(get(a,b),get(i,j));
                }
            }
            
        }
    }
    
    int t=bfs();
    
    if(t>0x3f3f3f3f/2)puts("-1");
    else cout<<t;

    
    return 0;
}

我的代码,实在想不出来咋连接虫洞,后续有想法在更新哈

#include<bits/stdc++.h>
using namespace std;
int a[1005][1005], n, dis[1005][1005];
queue<pair<int,int>> q;

const int dx[] = {0, 0, -1, 1};
const int dy[] = {-1, 1, 0, 0};

int bfs(int x, int y) {
    pair<int,int> now;now.first=x,now.second=y;
    q.push(now);
	memset(dis, 0x3f, sizeof(dis));
	dis[x][y] = 0;
	while(!q.empty()) {
        now=q.front();q.pop();
        x=now.first,y=now.second;
		for(int i = 0; i < 4; i++) {
			int bx = x + dx[i], by = y + dy[i];
			if(bx < 1 || by < 1 || bx > n || by > n) continue;
			if(a[bx][by]) continue;
			if(dis[bx][by] > dis[x][y]+1) {
				dis[bx][by] = dis[x][y] + 1;
				q.push({bx,by});
			}
		}
	}
	return dis[n][n];
}

int main() {
    int i,j,k;
    cin>>n;
    for(i=1;i<=n;i++)
        a[0][i]=a[i][0]=a[i][n+1]=a[n+1][i]=1;//棋盘的四周
	for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            cin>>a[i][j];
	int ans = bfs(1, 1);
	if(ans == dis[n+2][n+2]) cout << -1 << '\n';
	else cout << ans;
	return 0;
}

E 小红的序列乘积2.0

链接:https://ac.nowcoder.com/acm/contest/87656/E
来源:牛客网

题目描述

对于一个长度为 𝑚 的整数序列 {𝑏1,𝑏2,…,𝑏𝑚},定义𝑓𝑖=𝑏1×𝑏2×⋯×𝑏𝑖 ,即前 𝑖 项的乘积。这个序列的权值即为 𝑓1,𝑓2,…,𝑓𝑚 中个位数是 6 的数字个数。
小红有一个长度为 𝑛 的整数序列 {𝑎1,𝑎2,…,𝑎𝑛},她想知道这个序列全部 2𝑛−1 个非空子序列的权值和是多少。
如果序列 𝑎 可以通过删除序列 𝑏 中的若干(可能为零或全部)元素得到,则序列 𝑎 是序列 𝑏 的子序列。

输入描述:

第一行输入一个整数 𝑛(1≤𝑛≤105) 代表序列中元素的数量。
 第二行输入 𝑛 个整数 𝑎1,𝑎2,⋯ ,𝑎𝑛(1≤𝑎𝑖≤109) 代表序列元素。

输出描述:

在一行上输出一个整数,输出一个整数,表示全部子序列的权值和。由于答案可能很大,请将答案对 (109+7) 取模后输出。

示例1

输入
3
4 4 6
输出
4

说明

对于子序列 [4] ,没有贡献;
 对于子序列 [6] ,𝑓={6} 贡献为 1 ;
 对于子序列 [4,4] ,𝑓={4,16} 贡献为 1 ;
 对于子序列 [4,6] ,𝑓={4,24} ,没有贡献;
 对于子序列 [4,4,6] ,𝑓={4,16,96} 贡献为 2 。

示例2

输入
5
1 2 3 4 4
输出
12

题解

以下内容来自文心一言,感觉说的很有道理:
要解决这个问题,我们首先需要理解子序列权值的计算方式,并找到一个高效的方法来计算所有子序列的权值和。
解题思路
定义和观察:对于每个数字 a i ,我们考虑以它为结尾的所有子序列的乘积的个位数。
注意到,当我们将一个新的数字 a i 加到一个子序列的末尾时,该子序列的乘积的个位数仅由 a i 和原乘积的个位数决定。
个位数乘积的周期性:
任何整数与另一个整数相乘,其结果的个位数只与这两个整数的个位数有关。
个位数相乘的结果在 0-9 之间循环。
动态规划:
使用动态规划(DP)来记录以每个元素结尾的所有子序列的乘积的个位数为 0 到 9 的子序列数量。
初始化 DP 数组,其中 dp[i][j] 表示以第 i 个元素结尾,且乘积的个位数为 j 的子序列的数量。
转移方程:
对于每个元素 a i​ ,我们计算它的个位数 digit i =a i %10。
更新 DP 数组:dp[i][(j * digit_i) % 10] += dp[i-1][j] + 1(其中 +1 是因为单独 a i 本身也是一个子序列)。
计算权值:
遍历每个元素 a i 及其对应的 DP 数组,累加所有个位数为 6 的子序列数量。
取模运算:
在整个计算过程中,由于答案可能很大,需要在每一步都对 (10 ^ 9 +7) 取模。
伪代码

MOD = 10**9 + 7  
n = int(input())  
a = list(map(int, input().split()))  
dp = [[0] * 10 for _ in range(n + 1)]  
for i in range(n):  
    digit = a[i] % 10  
    for j in range(10):  
        dp[i+1][(j * digit) % 10] = (dp[i][j] + 1) % MOD  
        if i > 0:  
            dp[i+1][(j * digit) % 10] = (dp[i+1][(j * digit) % 10] + dp[i][(j * digit) % 10]) % MOD  
  
# 计算所有子序列的权值和  
answer = sum(dp[n][6])  
print(answer)

注意:上述伪代码需要一些调整,因为我们在计算 dp[i+1][…] 时直接使用了 dp[i][…] 的值,但在实际中,我们需要先保存 dp[i][…] 的值,因为 dp[i+1][…] 的计算可能会覆盖 dp[i][…]。此外,dp[i][…] 的初始值应设置为 0(除了 dp[0][…],这取决于题目是否考虑空序列)。在这个问题中,我们不考虑空序列,因此 dp[0][…] 可以保持为 0。
进一步优化
注意到我们其实不需要存储所有以每个元素结尾的子序列的信息,而只需要知道到当前位置为止,乘积个位数为 0-9 的子序列数量。
因此,我们可以使用一个一维数组 dp[10] 来代替二维数组,进一步减少空间复杂度。
这个解法的时间复杂度是 O(n×10),空间复杂度是 O(10)。

上面的解释有部分正确,但是不完全正确
这道题动态规划(数位dp),定义dp[i][j],表示的是到i位置有多少种个位数以数字结尾j的方案数
转移方程为 dp[i][j*a[i]%mod 10] = dp[i-1][j]+dp[i][j * a[i] mod 10] ,还可以一维数组滚动一下,如果当前位置的值乘上上一个位置结尾的个位数为6那就计算一下贡献。

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int maxn=1e5+5,mod=1e9+7;
int n,a[maxn],fac[maxn]={1};
int f[maxn][10],ans;
signed main(){
    int i,j,k;
    cin>>n;
    f[0][1]=1;
    for(i=1;i<=n;i++){
        cin>>a[i];
        a[i]%=10;
        fac[i]=1*fac[i-1]*2%mod;
    }
    for(i=1;i<=n;i++)
        for(j=1;j<10;j++){
            f[i][j]=(f[i][j]+f[i-1][j])%mod;
            f[i][j*a[i]%10]=(f[i][j*a[i]%10]+f[i-1][j])%mod;
            if(j*a[i]%10==6)ans=(ans+f[i-1][j]*fac[n-i]%mod)%mod;
        }
    printf("%d\n",ans);
    return 0;
}
F 灯下定影

链接:https://ac.nowcoder.com/acm/contest/87656/F
来源:牛客网

题目描述

为了省电,W星的灯都是感应灯,有人进入到感应区域后立即亮起(包含边界),在人离开区域后延迟一定时间熄灭。当然,如果在此期间有其他人进入感应区域,则重新开始计时。
 已知感应区域是以灯所在位置为中心的一个圆,有一些人同时从初始位置出发、沿给定的向量方向、以给定的速度运动。
  你能求解出路灯亮起的总时间吗。

输入描述:

第一行输入三个整数 𝑥0,𝑦0 和 𝑟 (−1000≤𝑥0,𝑦0≤1000; 1≤𝑟≤100)代表灯所在的位置和灯的感应区域半径。
 第二行输入两个整数 𝑛 和 𝑥 (1≤𝑛≤105; 0≤𝑥≤1000) 代表行人人数和延迟熄灭时间。
 此后 𝑛 行,每行输入五个小数点后位数不超过 9 位的实数 𝑢𝑠,𝑣𝑠,𝑢𝑒,𝑣𝑒 和 𝑠 (−1000≤𝑢𝑠,𝑣𝑠,𝑢𝑒,𝑣𝑒≤1000; 1≤𝑠≤1000) 代表行人初始位置、前进路线上的另一个点(注意不是终点)与移动速度,保证 (𝑢𝑠,𝑣𝑠)≠(𝑢𝑒,𝑣𝑒) 且 (𝑢𝑠,𝑣𝑠) 不位于灯的感应区域内。

输出描述:

在一行上输出一个实数,代表路灯亮起的总时间。如果相对误差或绝对误差不超过 10−6
,您的答案将被接受。具体来说,设您的答案为 𝑎 ,裁判的答案为 𝑏 ,当且仅当 max⁡(1,∣𝑏∣) / ∣𝑎−𝑏∣ ≤10−6 时,您的答案将被接受。

示例1

输入
4 2 6
3 2
14 -6 8 -4 1
10 4 0 -4 1
8.00 -4.000 0.00 -4.000 1
输出
17.719185869293

说明

该样例的示意图见下方所示。
在这里插入图片描述

● 对于第一个行人,其到达和离开感应区域的时间分别为 𝑡in1=7.96696376 和 𝑡out1=16.06634645
● 对于第二个行人,其到达和离开感应区域的时间分别为 𝑡in2=0.34716059 和 𝑡out2=11.52204531 所以,从 𝑡in2 到 𝑡out1 这段时间路灯一直都是亮着的,𝑡out1 时刻之后,路灯延迟 2 秒关闭。
● 对于第三个行人,其到达和离开感应区域的时间均为 𝑡in3=𝑡out3=2
最终亮起总时间 𝑡out1−𝑡in2+2=17.719186。

示例2

输入
-6 -9 9
5 0
-10 1 -3 -7 1
4 -7 -2 0 1
-7 1 -2 5 1
3 -6 -2 9 1
-9 4 -2 -1 1.000000001
输出
16.519229877697

题解

我太菜了(看不懂,根本不会做)下面时出题人的解释,丢个链接
https://ac.nowcoder.com/acm/discuss/blogs?tagId=270952
在这里插入图片描述
下面是大佬的模板

#include<bits/stdc++.h>

using i64 = long long;
using u64 = unsigned long long;

double eps = 1e-8;

struct point
{
    double x, y;
};

struct line
{
    point a, b;
};

double distance(point p1, point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

double distance(double x1,double y1,double x2,double y2) {
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

point intersection(point u1,point u2,point v1,point v2)
{
    point ret=u1;
    double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
    ret.x+=(u2.x-u1.x)*t;
    ret.y+=(u2.y-u1.y)*t;
    return ret;
}

void intersection_line_circle(point c,double r,point l1,point l2,point& p1,point& p2)
{
    point p=c;
    double t;
    p.x+=l1.y-l2.y;
    p.y+=l2.x-l1.x;
    p=intersection(p,c,l1,l2);
    t=sqrt(r*r-distance(p,c)*distance(p,c))/distance(l1,l2);
    p1.x=p.x+(l2.x-l1.x)*t;
    p1.y=p.y+(l2.y-l1.y)*t;
    p2.x=p.x-(l2.x-l1.x)*t;
    p2.y=p.y-(l2.y-l1.y)*t;
}

double xmult(point p1,point p2,point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

double disptoline(point p,point l1,point l2)
{
    return fabs(xmult(p,l1,l2))/distance(l1,l2);
}

int intersect_line_circle(point c,double r,point l1,point l2)
{
    return disptoline(c,l1,l2)<r+eps;
}

std::vector<std::pair<double, double>> segs;
//区间合并
void merge(std::vector<std::pair<double, double> > &segs)
{
    std::vector<std::pair<double, double>> res;//用来存储
    //按区间的左端点来进行排序,然后再按照第二个排序(pair很像)
    std::sort(segs.begin(),segs.end());
    double st = -2e9, ed = -2e9;
    for(auto seg : segs)
    {
        //如果比较区间的左端点不在当前区间中
        if(ed < seg.first)
        {
            //判断一下是否更新 新的当前区间(以防第一次更新)
            if(st!=-2e9) res.push_back({st,ed});
            st = seg.first,ed = seg.second;//更新区间,变成当前区间
        }
        //如果比较区间的左端点在区间中更新一下最大的右端点
        else ed = std::max(ed,seg.second); 
    }
    //看一下,最后一个元素是否被合并
    if(st!=-2e9) res.push_back({st,ed});
    
    segs = res;
}


void solve() {
    double x0, y0, r;
    std::cin >> x0 >> y0 >> r;
    point p0 = {x0, y0};

    int n;
    double x;
    std::cin >> n >> x;
    for (int i = 1; i <= n; i++) {
        double sx, sy, tx, ty, v;
        std::cin >> sx >> sy >> tx >> ty >> v;

        point pl1 = {sx, sy}, pl2 = {tx, ty};
        point p1, p2;
        intersection_line_circle(p0, r, pl1, pl2, p1, p2);
        
        if (intersect_line_circle(p0, r, pl1, pl2) == 0) continue;

        double tp1 = pl2.x - pl1.x;
        double tp2 = p2.x - pl1.x;
		
        //这里在判断射线的方向是否能与圆有交点,因为两个点一定不重合,先判一下射线x的方向与交点方向
        //如果射线是平行与y轴的就用纵坐标去判断是否相交。
        if(tp1 != 0) {
            // std::cout << tp1 << '\n';
            if ((tp1 > 0 && tp2 < 0) || (tp1 < 0 && tp2 > 0)) continue;
        }
        else {
            tp1 = pl2.y - pl1.y;
            tp2 = p2.y - pl1.y;
            if ((tp1 > 0 && tp2 < 0) || (tp1 < 0 && tp2 > 0)) continue;
        }

        double dis1 = distance(pl1, p1);
        double dis2 = distance(pl1, p2);

        if (dis1 - dis2 > 0) std::swap(dis1, dis2);
        segs.push_back({dis1 / v, dis2 / v + x});
    }

    merge(segs);

    double ans = 0;
    for (auto [l, r] : segs) {
        // std::cout << l << ' ' << r << '\n';
        ans += r - l;
    }

    std::cout << std::fixed << std::setprecision(12) << ans << '\n';
}

signed main() {
    std::ios::sync_with_stdio(0);
    std::cout.tie(0);
    std::cin.tie(0);
    i64 t = 1;
    // std::cin >> t;
    while (t--) {
        solve();
    }
} 

总结

1 2 题签到
第3题有点坑人
第4题BFS搜索,理论简单,但是代码量不低,而且有点不好写
第5题数位DP,考场上没想到,应该积累
第6题计算几何,不在考虑范围之内

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洋洋的计算机刷题日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值