标签:
原题是这份导刊模拟的第二题
不给你们完整的样例数据,因为我丢了=。=
开工。
*以下用到的变量名: 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