今天早晨一来就是一场猝不及防的考试(说好的下午考呢?)
于是没有打卡(其实打了也是模拟赛爆零)
T1:
这题一看不可做啊......
数据范围显然是nlogn,大概复杂度全都在排序。
好,我们开始推结论什么的,一个人能感染到的人一定是前面比他快或者后面比他慢。
然后呢?感染有时间顺序,所以我们能按照时间建图,存在点数O(n^3)的大力DP。
but,多个人同时相遇怎么办?不会DP了,弃坑弃坑。
写了10分爆搜然后写挂爆零了。
关于这题正解?
如果我们让时间趋于正无穷,那么这些人的顺序一定是按照速度排序的。
考虑一个人能感染那些人?起始点在他前且速度比他快的,起始点在他后且比他慢的。
那么,每个人在这个序列上能感染的区间就是[起始点比在他后的人且比他慢的中最慢的,起始点在他前的人且比他快的中最快的]。
为什么?显然这个区间外的人都不能被感染(那些人一定是在前且慢或者在后且块)。
对于区间内速度大于当前点的点,如果速度比右端点慢且在初始位置当前点右,那么他会被已经被感染的右端点感染。
如果速度比左端点慢且初始位置在左,那么因为他比当前点快,一定会被当前点直接感染。
左边情况同理。
考场爆零代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 const int maxn=17; 6 const double eps=1e-8; 7 8 struct Node { 9 double t; 10 int u,v; 11 Node() {} 12 Node(double tt,int uu,int vv) { t = tt , u = uu , v = vv ; } 13 friend bool operator < (const Node &a,const Node &b) { 14 return a.t < b.t; 15 } 16 }ns[maxn*maxn]; 17 18 int x[maxn],v[maxn],used[maxn],vis[maxn],n,cnt,ans; 19 20 inline void gnode(int a,int b) { 21 if( x[a] < x[b] && v[a] < v[b] ) return; 22 ns[++cnt] = Node((double)(x[b]-x[a])/(v[a]-v[b]),a,b); 23 } 24 inline void check() { 25 memcpy(vis+1,used+1,sizeof(int)*n); 26 for(int i=1,j,tp;i<=cnt;i=j+1) { 27 j = i , tp = 0; 28 while( j < cnt && std::fabs(ns[j+1].t-ns[i].t) <= eps ) ++j; 29 for(int k=i;k<=j;k++) tp |= ( vis[ns[k].u] | vis[ns[k].v] ); 30 for(int k=i;k<=j;k++) vis[ns[k].u] |= tp , vis[ns[k].v] |= tp; 31 } 32 for(int i=1;i<=n;i++) if( !vis[i] ) return; 33 ++ans; 34 } 35 inline void dfs(int pos) { 36 if( pos > n ) return check(); 37 used[pos] = 0 , dfs( pos + 1 ) , 38 used[pos] = 1 , dfs( pos + 1 ) ; 39 } 40 41 int main() { 42 scanf("%d",&n); 43 for(int i=1;i<=n;i++) scanf("%d%d",x+i,v+i); 44 for(int i=1;i<=n;i++) 45 for(int j=i+1;j<=n;j++) 46 gnode(i,j); 47 std::sort(ns+1,ns+1+cnt); 48 dfs(1); 49 printf("%d\n",ans); 50 return 0; 51 }