第一种比较笨重的做法
#include<stdio.h> #include<string.h> #include<ctype.h> #include<math.h> #include<iostream> #include<string> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} const int N=1010,M=0,Z=1e9+7,ms63=1061109567; int casenum,casei; int n; struct A { int t,st,ed,t2,typ,o; bool operator < (const A& b)const {return t<b.t;} }a[N]; int v[N]; int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) { scanf("%d%d%d",&a[i].t,&a[i].st,&a[i].ed); a[i].t2=a[i].t+abs(a[i].ed-a[i].st); a[i].typ=a[i].st<a[i].ed?1:-1; a[i].o=i; } sort(a+1,a+n+1); MS(v,0); for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++)if(a[i].t2>=a[j].t) { int t=a[j].t-a[i].t;//求出时间差 int p=a[i].st+a[i].typ*t;//求出经过这个时间差后第一个人的位置 if(p==a[j].st) { ++v[a[i].o]; ++v[a[j].o]; continue; } if(a[i].typ==a[j].typ)continue; if(a[i].typ==1&&p<=a[j].st)//如果i右走,j就必定向左走 { t=min(a[i].t2,a[j].t2)-a[j].t; int p1=p+t; int p2=a[j].st-t; if(p1>=p2) { ++v[a[i].o]; ++v[a[j].o]; } } if(a[i].typ==-1&&p>=a[j].st)//如果i左走,j就必定向右走 { t=min(a[i].t2,a[j].t2)-a[j].t; int p1=p-t; int p2=a[j].st+t; if(p1<=p2) { ++v[a[i].o]; ++v[a[j].o]; } } } } for(int i=1;i<=n;i++)printf("%d ",v[i]); puts(""); } return 0; } /* 【trick&&吐槽】 我是傻叉,既然把人都排序过了,那编号对应也不一样了。 映射要映射到人的编号上,细节要十分注意啊啊啊啊! 【题意】 有n([2,1000])个人去散步,每个人都始终保持这1m/s的速度 每个人有三个参数t[i],st[i],ed[i],st[i]!=ed[i] t[i]表示第i个人开始散步的时间. st[i]、ed[i]分别表示第i个人走路的起点和终点 我们想输出每个人分别与其他几个人打招呼。 (t[i],st[],ed[]都是1e6范围的数) 【类型】 暴力 【分析】 我们发现,这题小的是n,于是我们直接枚举每两个人,看看他俩是否打过招呼即可! 具体如何实现呢? 1,我们要按照时间的早晚排序,对于每个pair(先出发的人i,后出发的人j) 2,i的结束时间要比j的开始时间要晚 3,i先要到达j的出发时间,如果位置一样,那肯定可以打招呼 4,现在两个人方向必须相逆,然后必须在现阶段越走越近 5,我们求出两个人同时在场的最晚时间 6,求出最晚时间下的两个人的位置,如果发生了交错,那说明打了招呼 【时间复杂度&&优化】 O(n^2) */
第二种比较优美的做法
#include<stdio.h> #include<string.h> #include<ctype.h> #include<math.h> #include<iostream> #include<string> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} const int N=1010,M=0,Z=1e9+7,ms63=1061109567; int casenum,casei; int n; struct A { int t1,t2,st,ed,typ; }a[N]; int v[N]; int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) { scanf("%d%d%d",&a[i].t1,&a[i].st,&a[i].ed); a[i].t2=a[i].t1+abs(a[i].ed-a[i].st); a[i].typ=a[i].st<a[i].ed?1:-1; } MS(v,0); for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { int t1=max(a[i].t1,a[j].t1); int t2=min(a[i].t2,a[j].t2); if(t1>t2)continue; LL pi1=a[i].st+(t1-a[i].t1)*a[i].typ; LL pi2=a[i].st+(t2-a[i].t1)*a[i].typ; LL pj1=a[j].st+(t1-a[j].t1)*a[j].typ; LL pj2=a[j].st+(t2-a[j].t1)*a[j].typ; if((pi1-pj1)*(pi2-pj2)<=0) { ++v[i]; ++v[j]; } } } for(int i=1;i<=n;i++)printf("%d ",v[i]); puts(""); } return 0; } /* 【trick&&吐槽】 我是傻叉,既然把人都排序过了,那编号对应也不一样了。 映射要映射到人的编号上,细节要十分注意啊啊啊啊! 【题意】 有n([2,1000])个人去散步,每个人都始终保持这1m/s的速度 每个人有三个参数t[i],st[i],ed[i],st[i]!=ed[i] t[i]表示第i个人开始散步的时间. st[i]、ed[i]分别表示第i个人走路的起点和终点 我们想输出每个人分别与其他几个人打招呼。 (t[i],st[],ed[]都是1e6范围的数) 【类型】 暴力 【分析】 我们发现,这题小的是n,于是我们直接枚举每两个人,看看他俩是否打过招呼即可! 具体如何实现呢? 1,我们要按照时间的早晚排序,对于每个pair(先出发的人i,后出发的人j) 2,i的结束时间要比j的开始时间要晚 3,i先要到达j的出发时间,如果位置一样,那肯定可以打招呼 4,现在两个人方向必须相逆,然后必须在现阶段越走越近 5,我们求出两个人同时在场的最晚时间 6,求出最晚时间下的两个人的位置,如果发生了交错,那说明打了招呼 其实总结起来,就是找出两个人都在的条件下的最早时间和最晚时间。 然后看位置大小关系是否发生过错位。于是我们引入更优美的代码—— 直接求出两个人共存时间下的(i位置1,j位置1)和(i位置2,j位置2),然后用乘法<=0判定即可。 【时间复杂度&&优化】 O(n^2) */