题意:
一只特别的蚂蚁,只能直走或者左转。在一个平面上,有很多株植物,这只蚂蚁每天需要进食一株,这只蚂蚁从起点为(0,miny)的点开始出发。求最多能活多少天
分析:
肯定是可以吃到所有植物的,以当前方向无限延长成直线,可以剩余的植物都在直线的左边。所以就是求上一个位置到当前位置与下一个位置与当前位置的夹角,并且使夹角最大。
cos(0~pi)是单调递减的,夹角越大,cos值越小。所以我用点积来计算。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #define eps 1e-8 #define INF 1e9 using namespace std; const int maxn=100; typedef struct Point { double x,y; Point() {}; Point(double xx,double yy) { x=xx; y=yy; } } Vector; double crs_prdct(Vector a,Vector b) { return a.x*b.y-b.x*a.y; } double dot_prdct(Vector a,Vector b) { return a.x*b.x+a.y*b.y; } Vector operator - (Point a,Point b) { return Vector(a.x-b.x,a.y-b.y); } double dist(Vector v) { return sqrt(v.x*v.x+v.y*v.y); } double dist(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } Point pot[maxn]; bool vis[maxn]; int main() { // freopen("in.txt","r",stdin); int t,n; scanf("%d",&t); while(t--) { scanf("%d",&n); int idx; double x,y; int minp=1; for(int i=1; i<=n; i++) { scanf("%d%lf%lf",&idx,&x,&y); pot[i]=Point(x,y); if(y==pot[minp].y) minp=x<pot[minp].x? i:minp; if(y<pot[minp].y) minp=i; } pot[0]=Point(0,pot[minp].y); memset(vis,0,sizeof(vis)); int last=0,now=minp; printf("%d %d",n,now); vis[now]=1; for(int i=2; i<=n; i++) { int next; Vector now_v=Vector(pot[last]-pot[now]); double cosA=INF; for(int j=1; j<=n; j++) { if(vis[j]) continue; Vector next_v=Vector(pot[j]-pot[now]); double cosB=dot_prdct(now_v,next_v)/dist(now_v)/dist(next_v); if(cosB<cosA) { cosA=cosB; next=j; } } printf(" %d",next); vis[next]=1; last=now; now=next; } puts(""); } return 0; }