蓝桥杯训练——蚂蚁感冒

题目链接:https://www.dotcpp.com/oj/contest2388_problem0.html

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <cstdio>
#include <string>
#include <stack>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
typedef long long ll;
ll a[60];
bool cmp(ll x,ll y){
    return abs(x)<abs(y);
}
bool bing[60];
bool vis[60];
//生病的蚂蚁
int main()
{
    IOS;
    ll n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    bing[abs(a[0])]=true;//得病蚂蚁
    sort(a,a+n,cmp);//按坐标排序(去掉方向)
    ll ans=1;//统计生病蚂蚁数量
//--------------------------------------------------------------------------------
    //一轮一轮的去掉能走出去的蚂蚁
    for(int l=0,r=n-1;l<r;){
        //------两边的蚂蚁并且方向指向外侧肯定不用碰撞就能走出去了---------------------
        while(l<r&&a[l]<0){
            l++;
        }
        while(l<r&&a[r]>0){
            r--;
        }
        //----------------------------------------------------------------------
        if(l==r)break;//就剩一只蚂蚁了
        for(int k=l;k<=r;k++)vis[abs(a[k])]=false;//初始化默认a[k]这只蚂蚁在此轮相撞
        //-------------接下来判断每只蚂蚁的传染情况,有无相撞-----------------------
        for(int k=l;k<r;k++){
            if(a[k]>0&&a[k+1]<0){//蚂蚁相撞的情况唯一条件
                //蚂蚁传染的唯一条件是一个有病另一个没病
                if(bing[abs(a[k])]&&!bing[abs(a[k+1])]){
                    ans++;bing[abs(a[k+1])]=true;//被传染
                }
                else if(!bing[abs(a[k])]&&bing[abs(a[k+1])]){
                    ans++;bing[abs(a[k])]=true;
                }
            }
            else if(a[k]>0&&a[k+1]>0){//蚂蚁不相撞的第一种情况,a[k]这轮肯定不会相撞
                vis[abs(a[k])]=true;//不会相撞
            }
            else if(a[k]<0&&a[k+1]<0){//蚂蚁不相撞的第二种情况,a[k+1]这轮肯定不会相撞
                vis[abs(a[k+1])]=true;//不会相撞
            }
            //这里为什么不列出相背而行的情况呢,这个也不相撞啊?
            //其实这种情况不用判断,因为这种情况我们不能确定哪一个蚂蚁不会相撞
            //例如:a[k]可能和a[k-1]相撞,a[k+1]可能和a[k+2]相撞
        }
        //-------------------------------------------------------------------
        //--------做出每一轮相撞蚂蚁的反转--------------------------------
        for(int k=l;k<=r;k++){
            if(vis[(abs(a[k]))])continue;
            a[k]=0-a[k];
        }
        //-------------------------------------------------------------
    }
//------------------------------------------------------------------------------
    cout<<ans<<endl;
    getchar();
    getchar();
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值