码迷,mamicode.com
首页 > 其他好文 > 详细

【技术向】蚂蚁

时间:2015-09-24 22:30:37      阅读:307      评论:0      收藏:0      [点我收藏+]

标签:

原题是这份导刊模拟的第二题

技术分享

不给你们完整的样例数据,因为我丢了=。=

开工。

    *以下用到的变量名:  Size:地图宽度

 

    我想了三种写法

1.同时移动,排序之后判重,时间复杂度是O(Size*nlog2n)  但是由于判重太难写,放弃

2.同时移动,哈希判重,使用 h(k) = (x[k] * Size + y[k]) mod p   , 时间复杂度O(Size*n)    老是出错,放弃

3.换一种思路,可以“实验”出所有的碰撞事件,然后根据事件的时间进行推导,时间复杂度O(Size*n2)--à我实现了这个

4*.根据3,推导一个玄学公式(显然是可行的),预判相撞时间,时间复杂度O(n2)

5*.根据4的玄学,维护一个线段树套线段树,用这个求会和某一蚂蚁相撞的所有蚂蚁,时间复杂度O(n(log2n)2)

第一步,搞定一些细节问题

    设其中两只蚂蚁相撞于(xt,yt),有可能,xt,yt是实数,小数点后为0.5,故将整个地图的单位长度翻倍。

 

第二步,解决四个方向,如下

West,横坐标+1

East, 横坐标-1

North,纵坐标+1

South,纵坐标-1

 

根据四种方向设计函数move(int&x,int&y,char c),表示根据c的移动方向,运动时间为1,改变(x,y)

    根据三的规则,我们对于每一对蚂蚁<i,j>进行碰撞测试,同时模拟二者的运动过程,在相撞或有一只蚂蚁出地图为止,记录两只蚂蚁的编号i、j和预计相撞事件的发生时间t

    如果有两个时间t1,t2,有t1<t2,因为蚂蚁是会消失的,故在t1时预计会发生碰撞的两只蚂蚁,不会参与t2的碰撞。

    另一种情况,如果有两个时间t1,t2,有t1=t2,由于多只蚂蚁在同一个点会发生碰撞,那么所有的蚂蚁都要消失。

    那么我们根据t为关键字,升序排列实验中收集到的所有碰撞事件。

设计一个数组{vis[i]},vis[i]=j表示蚂蚁i在时间j时消失了,根据上面两条规则判断,记录vis[i],扫描出所有的存在的蚂蚁,即为答案

①    一共有n2个<i,j>的时间复杂度是O(n2),但是每个蚂蚁都会被模拟Size遍,变成O(Size*n2)

②    如果使用快速排序,那么时间复杂度是O(nlog2n)

③    显然这个是O(n2)的

故该算法时间复杂度为O(Size*n2)

 

【下面是未经证明的玄学算法】

时间复杂度:O(n2)

算法流程:

《我觉得这个叫算法流程会被打》<<-这里面有字

    对于一对蚂蚁<x,y><a,b>,移动为c1,c2,推导如下

分类讨论移动方向

    c1=N,c2=S,若x=a,y<b那么t=(y+b)/2;

    c1=E,c2=W,若y=b,x<a 那么t=(x+a)/2;

    c1=W,c2=N,若x-a=y-b那么t=x-a;

    …

    类似的,我们可以讨论出剩下的所有情况(WS,ES,EN)(我隐约觉得有一个不用分这么多类的方法)

    诶,貌似可以走一步判趋势…事实上无论再简化到一个语句解决四个判断,与四个语句是等价的,但是这里是有讨论空间的。

 

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int g,n,m,ans;
int vis[51];
struct data{
    int u,v,t;
}e[3000];
struct Pair{
    int first,second;
    char mov;
}p[51];
bool move(int &a,int &b,char c){
    if(c==N)  b+=1;
    if(c==S)  b-=1;
    if(c==W)  a-=1;
    if(c==E)  a+=1;
    if(a>2000 || a<-2000)   return 0;
    if(b>2000 || b<-2000)   return 0;
    return 1;
}
int test(int a,int b){
    int t=0;
    int x1=p[a].first,y1=p[a].second,x2=p[b].first,y2=p[b].second;
    char c1=p[a].mov,c2=p[b].mov;
    while(move(x1,y1,c1)&&move(x2,y2,c2)){
        t++;
        if(x1==x2&&y1==y2){
            m++;
            e[m].u=a;
            e[m].v=b;
            e[m].t=t;
            return 1;
        }
    }
}
int cmp1(const data&a,const data&b){
    return a.t<b.t;
}
int cmp2(const Pair&a,const Pair&b){
    return a.first<b.first||(a.first==b.first&&a.second<b.second);
}
int main(){
    freopen("ant.in","r",stdin);
    freopen("ant.out","w",stdout);
    cin>>g;
    for(int I=1;I<=g;I++){
        cin>>n;
        for(int i=1;i<=n;i++)   cin>>p[i].mov;
        for(int i=1;i<=n;i++){
            cin>>p[i].first>>p[i].second;
            p[i].first<<=1;p[i].second<<=1;
        }
        sort(p+1,p+n+1,cmp2);
//        for(int i=1;i<=n;i++){
//            cout<<p[i].first<<‘ ‘<<p[i].second<<endl;
//        }
        for(int i=1;i<n;i++)    for(int j=i+1;j<=n;j++)     test(i,j);
        sort(e+1,e+m+1,cmp1);
        for(int i=1;i<=m;i++)/*
            printf("%d(%c)->(%d,%d) %d(%c)->(%d,%d) %d\n",  e[i].u,
                                                            p[e[i].u].mov,
                                                            p[e[i].u].first,
                                                            p[e[i].u].second,
                                                            e[i].v,
                                                            p[e[i].v].mov,
                                                            p[e[i].v].second,
                                                            p[e[i].v].second,
                                                            e[i].t);*/
        for(int i=1;i<=m;i++){
            int x=e[i].u,y=e[i].v;
            if(vis[x]==0&&vis[y]==0){
                vis[x]=vis[y]=e[i].t;
                ans+=2;
            }
            else
                if(vis[x]==e[i].t&&vis[y]==0){
                    vis[y]=e[i].t;
                    ans+=1;
                }
                else
                    if(vis[y]==e[i].t&&vis[x]==0){
                        vis[x]=e[i].t;
                        ans+=1;
                    }
        }
        printf("%d\n",n-ans);
        ans=0;m=0;memset(vis,0,sizeof(vis));
    } 
    return 0;
}

 

【技术向】蚂蚁

标签:

原文地址:http://www.cnblogs.com/oierforever/p/4836657.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!