病毒传播c++

【问题描述】

   在一个风景秀丽的小镇,一天早上,有 N 名晨跑爱好者(编号 1 ~ N )沿着优雅的江边景观道朝同一方向进行晨跑,第 i 名跑者从位置 Si 处起跑, 且其速度为 Vi。换句话说,对所有的实数 t ≥ 0,在时刻 t 时第 i 名跑者的位置为 Si + Vi ·t。 

   很不幸的是,其中一名跑者在 t = 0 的时刻感染了病毒,且是无症状感染者,这种病毒只会在同一时刻处在同一位置的跑者之间传播,新感染了病毒的跑者也会感染其他人,很显然,等待足够长的时间,那么病毒会感染一些特定的跑者。

   事后发现其中有一名跑者感染了病毒,如果此人就是在 t = 0 时刻的那名感染者,那么,在 N 名晨跑爱好者中会有多少人感染病毒?

【输入形式】

    输入包含三行:

第一行包含为两个整数 N 和 K,分别表示运动员的人数以及开始时感染了病毒的跑者编号。

第二行包含 N 个正整数 S1、S2、…、SN,用空格隔开,分别表示跑者的起始位置。

第三行包含 N 个正整数 V1、V2、…、VN,用空格隔开,分别表示跑者的速度。

【输出形式】

     输出为一个整数,表示最终被感染人数。

【样例输入】

6 3
3 9 8 5 7 5
6 6 5 4 6 3
【样例输出】

3
【样例说明】
【评分标准】

 对于50%的评测用例,0< K ≤ N ≤10^2

 对于70%的评测用例,0< K ≤ N ≤10^4

 对于90%的评测用例,0< K ≤ N ≤10^6

 对于100%的评测用例,0< K ≤ N ≤10^7

思路

首先,最基本的输入没有问题吧,你也可以不开动态数组,都随便的哈

int n, k;
cin >> n >> k;
int* s = new int[n+1];
for (int i = 1; i < n + 1; i++)
{
    cin >> s[i];
}
int* v = new int[n+1];
for (int j = 1; j < n + 1; j++)
{
    cin >> v[j];
}

然后,就到了判断环节

分为两次判断

第一次是倒霉蛋,一开始就和感染者在一个位置,还要判断一定会被感染的人

int sum = 0;//记录感染者总数
//一定会被感染的人
for (int i = 1; i <= n; i++)
{   
    //位置在感染者后面但是速度快或者在感染者前面但是速度慢(因为不限时,总会有追上的时候)
    //我们把会被感染的人中的最大速度和最小速度记录下来,我们最后还要判断在感染者右边而且速度也比第一个感染者快,但是如果他比会感染的人的最大速度慢的话,他还是会被感染
    if ((s[i] < s[k] && v[i] > v[k]) || (s[i] > s[k] && v[i] < v[k]))
    {//这里为什么不sum++呢,因为我后面一个循环就也会把这种情况判断一次
        mymax = max(mymax, v[i]);
        mymin = min(mymin, v[i]);
    }//这里用到了max和min函数,注意要加头文件algorithm
    if (s[i] == s[k])//单纯的倒霉蛋
    {
        sum++;
        mymax = max(mymax, v[i]);
        mymin = min(mymin, v[i]);
    }
}

因为我们判断的最小速度一定是v[i]<v[k]里面的,最大速度一定是v[i]>v[k]里面的,所以后面的判断就不存在最小速度的感染者在左边,因此左边的人的速度只要<=mymin就一定不会被感染

第二次判断就是找出除了一开始的倒霉蛋的其他感染者

for (int i = 1; i <= n; i++)
{
//注意!!!!!!!这里的最小速度和最大速度均是已经确定的感染者的,不是所有人的
//如果在初始感染者左边速度比最小速度快,那么一定会超过最小速度的这个感染者
//同理,如果在感染者右边比最大速度慢,那么一定会被最大速度的这个感染者追上
    if ((s[i] < s[k] && v[i] > mymin) || (s[i] > s[k] && v[i] < mymax))
    {
        sum++;
    }
}

最后就上完整的代码吧

#include<iostream>
#include <algorithm>
using namespace std;
int mymax = 0, mymin = 1000;
int main()
{
    int n, k;
    cin >> n >> k;
    int* s = new int[n+1];
    for (int i = 1; i < n + 1; i++)
    {
        cin >> s[i];
    }
    int* v = new int[n+1];
    for (int j = 1; j < n + 1; j++)
    {
        cin >> v[j];
    }
    int sum = 0;
    for (int i = 1; i <= n; i++)
    {
        //被感染
        if ((s[i] < s[k] && v[i] > v[k]) || (s[i] > s[k] && v[i] < v[k]))
        {
            mymax = max(mymax, v[i]);
            mymin = min(mymin, v[i]);
        }
        if (s[i] == s[k])
        {
            sum++;
            mymax = max(mymax, v[i]);
            mymin = min(mymin, v[i]);
        }
    }
    for (int i = 1; i <= n; i++)
    {
        if ((s[i] < s[k] && v[i] > mymin) || (s[i] > s[k] && v[i] < mymax))
        {
            sum++;
        }
    }
    cout << sum;
    delete[]s;
    delete[]v;
    return 0;
}

记得一键三连哦


  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无意识程序猿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值