注册 登录
编程论坛 C语言论坛

求助各位大神指点迷津蓝桥杯蚂蚁感冒问题

Emmaer123 发布于 2019-10-14 23:04, 2790 次点击
长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。
每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。
当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。
这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。
请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。
输入
第一行输入一个整数n  (1  <   n  <   50),  表示蚂蚁的总数。
接着的一行是n个用空格分开的整数  Xi  (-100  <   Xi  <   100),  Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数  据代表的蚂蚁感冒了。
输出
要求输出1个整数,表示最后感冒蚂蚁的数目。
样例输入
5
-10  8  -20  12  25
样例输出
3


//思路:若满足 相邻的两个数组 第一个大于零第二个小于零 的条件  那么这两个会相撞  所以检查数组中每两个相邻元素  
#include <stdio.h>
int main()
{
    int i,n,flag,count=0;
    char a[1000]={0};char b[1000]={1}; //b[i]=0记录第i只蚂蚁没感染,由题意可知b[0]=1即第一个元素为感染蚂蚁
   
    scanf("%d",&n);
    for (i=0;i<n;i++)  { scanf("%s",&a[i]);}
   
    do
       {
            flag=0;
         for(i=0;i<n-1;i++)
          {
            if(a[i]>0&&a[i+1]<0)     
            {// 如检查到符合的情况,将这两个元素a[i]、a[i+1]分别变成各自的相反数
                a[i]=0-a[i];
                a[i+1]=0-a[i+1];
                i++;// i++是为了跳过a[i+1],从而在下一次循环检查a[i+2]和a[i+3]正负
                if(b[i+1]!=b[i])   //若相邻两只蚂蚁中有一只感染
                {
                    b[i+1]=1;b[i]=1;  //将两只都记录为感染   
                    count++;
                }
                flag=1;
            }
             }
       }
    while(flag=1);  // 每从i=0循环至i=n-1完,检查flag,当flag=0说明没有相邻的元素满足条件,不会有蚂蚁感染了,于是跳出循环
   
    printf("%d",count);
    return 0;
 }
 
跪求为啥编译不出来,不知道思路哪里错了,求路过大神指点一下我的思路错在哪里
我的思路是:若满足 相邻的两个数组元素第一个大于0第二个小于0的条件  那么这两个会相撞 ,当检测到满足条件的两个元素时,改变各自正负(因为由题意遇到会返回回头) ,并且如果其中只有一个感冒,感冒蚂蚁的个数加一,如此循环,直到检测不到满足条件的元素,说明以后不会有相撞的蚂蚁

[此贴子已经被作者于2019-10-15 21:47编辑过]

11 回复
#2
rjsp2019-10-15 10:49
这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。
是仅有这一只蚂蚁可以感染其它蚂蚁,还是所有感冒的蚂蚁都可以感染其它蚂蚁?
#3
Emmaer1232019-10-15 12:56
回复 2楼 rjsp
应该是只要是被感染过的蚂蚁碰到其他蚂蚁就可以感染
#4
rjsp2019-10-15 13:16
那你试试
程序代码:
#include <stdio.h>
#include <stdlib.h>

unsigned foo( const int a[], unsigned n )
{
    unsigned left = 0; // 第一只病蚁左侧有几只朝向这只病蚁
    unsigned right = 0; // 第一只病蚁右侧有几只朝向这只病蚁
    for( unsigned i=0; i!=n; ++i )
    {
        left += ( abs(a[i])<abs(a[0]) && a[i]>0 );
        right += ( abs(a[i])>abs(a[0]) && a[i]<0 );
    }

    if( a[0]<0&&left==0 || a[0]>0&&right==0 ) // 第一只病蚁从未改向过
        return 1;
    return 1 + left + right;
}

int main( void )
{
    int a[50];
    unsigned n;
    scanf( "%u", &n );
    for( unsigned i=0; i!=n; ++i )
        scanf( "%d", &a[i] );

    printf( "%u\n", foo(a,n) );
}

#5
Emmaer1232019-10-15 16:46
回复 4楼 rjsp
我试了一下,结果正确,但我还是不明白我的思路错在哪里了
#6
rjsp2019-10-15 16:58
回复 5楼 Emmaer123
首先,一开始的 scanf("%s",&a[i]); 我就看不懂
#7
自学的数学2019-10-15 19:40
程序代码:

#include <cstdio>
#include <algorithm>

 
using namespace std;
struct Node
{
    int x;
    int dis;
    int num;
};
Node a[100];
int comp(Node a1,Node a2)
{
    if(a1.x!=a2.x)
        return a1.x<a2.x;
}
int main()
{
    int n,x;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",&x);
            a[i].dis=x<0?-1:1;
            a[i].x=abs(x);
            a[i].num=i+1;
        }
        sort(a,a+n,comp);  //排序
        int tmp=0,left=0,right=0,ans=0;
        for(int i=0;i<n;i++)  //左边向右走的
        {
            if(a[i].num==1)
            {
                tmp=i;break;
            }
            if(a[i].dis==1)
                left++;
        }
        for(int i=tmp+1;i<n;i++) //右边向左走的
        {
            if(a[i].dis==-1)
                right++;
        }
        if(a[tmp].dis==1 && right==0 || a[tmp].dis==-1 && left==0)
            ans=1;
        else
            ans=left+right+1;
        printf("%d\n",ans);
    }
    return 0;
}
#8
Emmaer1232019-10-15 21:49
回复 7楼 自学的数学
请大佬能不能指点下我的思路错在哪里呢?我想了很长时间,就是想不明白,太痛苦了。
我的思路是:若满足 相邻的两个数组元素第一个大于0第二个小于0的条件  那么这两个会相撞 ,当检测到满足条件的两个元素时,改变各自正负(因为由题意遇到会返回回头) ,并且如果其中只有一个感冒,感冒蚂蚁的个数加一,如此循环,直到检测不到满足条件的元素,说明以后不会有相撞的蚂蚁,可是我把我的程序运行以后结果是错的,真的百思不得其解

[此贴子已经被作者于2019-10-15 21:57编辑过]

#9
自学的数学2019-10-15 22:07
首先明白两只蚂蚁碰撞之后掉头和穿行过去是一样的,可以把穿行看做碰撞后掉头了,然后两个蚂蚁交换了,而是哪一只蚂蚁对结果不影响。

那么,假如第一只感冒蚂蚁向右走,那么碰到所有想左走的都会被感染,而感染后的蚂蚁必定是向左走的,那么他会把左边向右走的都感染了。

向左走的也是这样。

所以 ans = 左边向右走的  + 右边向左走的 + 1(本身)。

当然还有特殊情况,第一只感染的向右走,右边的都在向右走,那么速度一样的话它不会感染其他所有,所以 ans = 1,相反也是。
#10
Emmaer1232019-10-15 22:14
回复 9楼 自学的数学
其实我看过这个解法,也明白这个解法,这题有很多种思路,这次发帖主要是想弄明白自己的思路错在哪里,谢谢您花时间这么长的解释,但我现在还是非常困惑
#11
bcbbcclbbc2019-10-16 03:50
以下是引用rjsp在2019-10-15 16:58:46的发言:

首先,一开始的 scanf("%s",&a); 我就看不懂


一步一步来
题目要求输入的是整数
为什么你会想到定义字符数组,而不是整型数组
#12
bcbbcclbbc2019-10-16 21:47
回复 8楼 Emmaer123
我的思路是:若满足 相邻的两个数组元素第一个大于0第二个小于0的条件  那么这两个会相撞 ,当检测到满足条件的两个元素时,改变各自正负(因为由题意遇到会返回回头)

1,既然你说只要条件符合就改变元素正负,就说明你是想借用时间节点(相遇)来求结果,但是你就只改变符号不改变值(位置),不就是原地转圈了吗,怎么算出结论?
2,输入的数据只是一个一个的整数,代表他们的位置和方向,是随机性的,而你未对(位置)进行排序,怎么能直接用两个相邻的数组元素作为判断条件?
3,单纯一个整型数组,元素(只有位置和方向的信息)并没有感冒的信息,你是如何判断其是否感冒?
。。。
1