2012 Asia Hangzhou Regional Contest

Friend Chains http://acm.hdu.edu.cn/showproblem.php?pid=4460

图的最远两点距离,任意选个点bfs,如果有不能到的点直接-1.然后对于所有距离最远的点都bfs一次。最坏n^2

邻接表

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<queue>
 5 #include<map>
 6 #define mt(a,b) memset(a,b,sizeof(a))
 7 using namespace std;
 8 const int M=1024;
 9 char a[16],b[16];
10 map<string,int> name;
11 struct G{
12     struct E{
13         int v,next;
14     }e[M*20];
15     int le,head[M];
16     void init(){
17         le=0;
18         mt(head,-1);
19     }
20     void add(int u,int v){
21         e[le].v=v;
22         e[le].next=head[u];
23         head[u]=le++;
24     }
25 }g;
26 int dist[M],id[M];
27 bool vis[M];
28 queue<int> q;
29 void bfs(int s){
30     mt(vis,0);
31     mt(dist,-1);
32     vis[s]=true;
33     dist[s]=0;
34     while(!q.empty()) q.pop();
35     q.push(s);
36     while(!q.empty()){
37         int u=q.front();
38         q.pop();
39         for(int i=g.head[u];~i;i=g.e[i].next){
40             int v=g.e[i].v;
41             if(!vis[v]){
42                 vis[v]=true;
43                 dist[v]=dist[u]+1;
44                 q.push(v);
45             }
46         }
47     }
48 }
49 int main(){
50     int n,m;
51     while(~scanf("%d",&n),n){
52         name.clear();
53         for(int i=0;i<n;i++){
54             scanf("%s",a);
55             name[(string)a]=i;
56         }
57         scanf("%d",&m);
58         g.init();
59         while(m--){
60             scanf("%s%s",a,b);
61             int u=name[(string)a];
62             int v=name[(string)b];
63             g.add(u,v);
64             g.add(v,u);
65         }
66         bfs(0);
67         bool flag=false;
68         for(int i=0;i<n;i++){
69             if(dist[i]==-1){
70                 flag=true;
71                 break;
72             }
73         }
74         if(flag){
75             puts("-1");
76             continue;
77         }
78         int big=0;
79         for(int i=0;i<n;i++){
80             big=max(big,dist[i]);
81         }
82         int ld=0;
83         for(int i=0;i<n;i++){
84             if(dist[i]==big){
85                 id[ld++]=i;
86             }
87         }
88         int ans=0;
89         for(int i=0;i<ld;i++){
90             bfs(id[i]);
91             for(int j=0;j<n;j++){
92                 ans=max(ans,dist[j]);
93             }
94         }
95         printf("%d
",ans);
96     }
97     return 0;
98 }
View Code

 vector竟然还快些

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<queue>
 5 #include<map>
 6 #define mt(a,b) memset(a,b,sizeof(a))
 7 using namespace std;
 8 const int M=1024;
 9 char a[16],b[16];
10 map<string,int> name;
11 vector<int> g[M];
12 int dist[M],id[M];
13 bool vis[M];
14 queue<int> q;
15 void bfs(int s){
16     mt(vis,0);
17     mt(dist,-1);
18     vis[s]=true;
19     dist[s]=0;
20     while(!q.empty()) q.pop();
21     q.push(s);
22     while(!q.empty()){
23         int u=q.front();
24         q.pop();
25         int len=g[u].size();
26         for(int i=0;i<len;i++){
27             int v=g[u][i];
28             if(!vis[v]){
29                 vis[v]=true;
30                 dist[v]=dist[u]+1;
31                 q.push(v);
32             }
33         }
34     }
35 }
36 int main(){
37     int n,m;
38     while(~scanf("%d",&n),n){
39         name.clear();
40         for(int i=0;i<n;i++){
41             scanf("%s",a);
42             name[(string)a]=i;
43             g[i].clear();
44         }
45         scanf("%d",&m);
46         while(m--){
47             scanf("%s%s",a,b);
48             int u=name[(string)a];
49             int v=name[(string)b];
50             g[u].push_back(v);
51             g[v].push_back(u);
52         }
53         bfs(0);
54         bool flag=false;
55         for(int i=0;i<n;i++){
56             if(dist[i]==-1){
57                 flag=true;
58                 break;
59             }
60         }
61         if(flag){
62             puts("-1");
63             continue;
64         }
65         int big=0;
66         for(int i=0;i<n;i++){
67             big=max(big,dist[i]);
68         }
69         int ld=0;
70         for(int i=0;i<n;i++){
71             if(dist[i]==big){
72                 id[ld++]=i;
73             }
74         }
75         int ans=0;
76         for(int i=0;i<ld;i++){
77             bfs(id[i]);
78             for(int j=0;j<n;j++){
79                 ans=max(ans,dist[j]);
80             }
81         }
82         printf("%d
",ans);
83     }
84     return 0;
85 }
View Code

The Power of Xiangqi http://acm.hdu.edu.cn/showproblem.php?pid=4461

o(n)水题。每个旗子有权值,算一算权值比一比。注意至少1分。如果b和c有一个没有就扣一分。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 const int M=16;
 7 int sa[M],sb[M];
 8 int val[]={16,7,8,1,1,2,3};
 9 int main(){
10     int t,n;
11     char op[4];
12     while(~scanf("%d",&t)){
13         while(t--){
14             mt(sa,0);
15             mt(sb,0);
16             scanf("%d",&n);
17             while(n--){
18                 scanf("%s",op);
19                 sa[op[0]-'A']++;
20             }
21             scanf("%d",&n);
22             while(n--){
23                 scanf("%s",op);
24                 sb[op[0]-'A']++;
25             }
26             int suma=0,sumb=0;
27             for(int i=0;i<7;i++){
28                 suma+=val[i]*sa[i];
29                 sumb+=val[i]*sb[i];
30             }
31             if(!sa[1]||!sa[2]) suma--;
32             if(!sb[1]||!sb[2]) sumb--;
33             suma=max(1,suma);
34             sumb=max(1,sumb);
35             if(suma>sumb){
36                 puts("red");
37             }
38             else if(suma<sumb){
39                 puts("black");
40             }
41             else{
42                 puts("tie");
43             }
44         }
45     }
46     return 0;
47 }
View Code

Scaring the Birds http://acm.hdu.edu.cn/showproblem.php?pid=4462

二进制枚举放的情况,判断能否覆盖所有的玉米,注意能放的地方已经没有玉米了,不用判这个点。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 const int inf=0x3f3f3f3f;
 7 const int M=64;
 8 bool mat[M][M];
 9 struct G{
10     int x,y,r;
11 }p[16];
12 int one(int x){
13     int res=0;
14     while(x){
15         if(x&1) res++;
16         x>>=1;
17     }
18     return res;
19 }
20 int used[16];
21 int main(){
22     int n,m;
23     while(~scanf("%d",&n),n){
24         scanf("%d",&m);
25         mt(mat,0);
26         for(int i=0;i<m;i++){
27             scanf("%d%d",&p[i].x,&p[i].y);
28             mat[p[i].x][p[i].y]=true;
29         }
30         for(int i=0;i<m;i++){
31             scanf("%d",&p[i].r);
32         }
33         int all=1<<m;
34         int ans=inf;
35         for(int i=0;i<all;i++){
36             int now=one(i);
37             if(now>=ans) continue;
38             int lu=0;
39             for(int j=0;j<m;j++){
40                 if((i>>j)&1){
41                     used[lu++]=j;
42                 }
43             }
44             bool flag=true;
45             for(int x=1;x<=n;x++){
46                 for(int y=1;y<=n;y++){
47                     if(mat[x][y]) continue;
48                     bool ok=false;
49                     for(int j=0;j<lu;j++){
50                         int id=used[j];
51                         if(abs(x-p[id].x)+abs(y-p[id].y)<=p[id].r){
52                             ok=true;
53                             break;
54                         }
55                     }
56                     if(!ok){
57                         flag=false;
58                         break;
59                     }
60                 }
61                 if(!flag) break;
62             }
63             if(flag){
64                 ans=min(ans,now);
65             }
66         }
67         if(ans==inf) ans=-1;
68         printf("%d
",ans);
69     }
70     return 0;
71 }
View Code

Outlets http://acm.hdu.edu.cn/showproblem.php?pid=4463

最小生成树,必须有一条边先加进去,那就加个权值为零的,然后ans直接加上边权,这样就保证一定有这个边了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<algorithm>
  5 #define mt(a,b) memset(a,b,sizeof(a))
  6 using namespace std;
  7 const int M=64;
  8 class Kruskal { ///最小生成树(无向图)o(ME*logME)
  9     typedef double typec;///边权的类型
 10     static const int ME=M*M;///边的个数
 11     static const int MV=M;///点的个数
 12     class UnionFindSet { ///并查集
 13         int par[MV];
 14     public:
 15         void init() {
 16             mt(par,-1);
 17         }
 18         int getroot(int x) {
 19             int i=x,j=x,temp;
 20             while(par[i]>=0) i=par[i];
 21             while(j!=i) {
 22                 temp=par[j];
 23                 par[j]=i;
 24                 j=temp;
 25             }
 26             return i;
 27         }
 28         bool unite(int x,int y) {
 29             int p=getroot(x);
 30             int q=getroot(y);
 31             if(p==q)return false;
 32             if(par[p]>par[q]) {
 33                 par[q]+=par[p];
 34                 par[p]=q;
 35             } else {
 36                 par[p]+=par[q];
 37                 par[q]=p;
 38             }
 39             return true;
 40         }
 41     } f;
 42     struct E {
 43         int u,v;
 44         typec w;
 45         friend bool operator < (E a,E b) {
 46             return a.w<b.w;
 47         }
 48     } e[ME];
 49     int le,num,n;
 50     typec res;
 51 public:
 52     void init(int tn){///传入点的个数
 53         n=tn;
 54         le=res=0;
 55         f.init();
 56         num=1;
 57     }
 58     void add(int u,int v,typec w) {
 59         e[le].u=u;
 60         e[le].v=v;
 61         e[le].w=w;
 62         le++;
 63     }
 64     typec solve(){///返回-1不连通
 65         sort(e,e+le);
 66         for(int i=0; i<le&&num<n; i++) {
 67             if(f.unite(e[i].u,e[i].v)) {
 68                 num++;
 69                 res+=e[i].w;
 70             }
 71         }
 72         if(num<n) res=-1;
 73         return res;
 74     }
 75 }gx;
 76 struct point{
 77     double x,y;
 78 }p[M];
 79 double Distance(point p1,point p2) {
 80     return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
 81 }
 82 int main(){
 83     int n,x,y;
 84     while(~scanf("%d",&n),n){
 85         scanf("%d%d",&x,&y);
 86         for(int i=0;i<n;i++){
 87             scanf("%lf%lf",&p[i].x,&p[i].y);
 88         }
 89         gx.init(n);
 90         x--;
 91         y--;
 92         if(x>y) swap(x,y);
 93         for(int i=0;i<n;i++){
 94             for(int j=i+1;j<n;j++){
 95                 if(i==x&&j==y){
 96                     gx.add(i,j,0);
 97                 }
 98                 else{
 99                     gx.add(i,j,Distance(p[i],p[j]));
100                 }
101             }
102         }
103         double ans=Distance(p[x],p[y]);
104         ans+=gx.solve();
105         printf("%.2f
",ans);
106     }
107     return 0;
108 }
View Code

Stealing a Cake http://acm.hdu.edu.cn/showproblem.php?pid=4454

 从起点走到圆上任意一点,然后从那个点走到矩形上任意一点。求总的路程最小。

考虑起点到圆,只可能走两个切线之间,所以就有一个角度的限制,可以枚举这个角度,然后求出和圆的交点,然后再用这个交点求出到矩形最近距离,所有情况取个最小值。

设起点到圆心的直线sc与坐标轴夹角α。设sc与切线夹角θ 。则我们只要枚举0到θ,就能算出一个交点,注意,要取靠近s的交点。然后通过交点可以算出关于se直线的对称点。这样便枚举了所有可能的点的走法。

当前枚举到的直线斜率是 tan(θ+α) 又知道s经过这个直线,所以就可以算出直线上任意一点。然后就算直线和圆的交点,然后取近的交点,分别和矩形四个边算距离,也是取最小。对称点也同理可得。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<algorithm>
  4 using namespace std;
  5 const double eps=1e-8;
  6 const double pi=acos(-1.0);
  7 const int inf=0x3f3f3f3f;
  8 struct point {
  9     double x,y;
 10 } s,c,p[8]; ///起点,圆心,矩形
 11 double Distance(point p1,point p2) {
 12     return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
 13 }
 14 point intersection(point u1,point u2,point v1,point v2) {
 15     point ret=u1;
 16     double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x)) /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
 17     ret.x+=(u2.x-u1.x)*t;
 18     ret.y+=(u2.y-u1.y)*t;
 19     return ret;
 20 }
 21 void intersection_line_circle(point c,double r,point l1,point l2,point& p1,point& p2) {
 22     point p=c;
 23     double t;
 24     p.x+=l1.y-l2.y;
 25     p.y+=l2.x-l1.x;
 26     p=intersection(p,c,l1,l2);
 27     t=sqrt(r*r-Distance(p,c)*Distance(p,c))/Distance(l1,l2);
 28     p1.x=p.x+(l2.x-l1.x)*t;
 29     p1.y=p.y+(l2.y-l1.y)*t;
 30     p2.x=p.x-(l2.x-l1.x)*t;
 31     p2.y=p.y-(l2.y-l1.y)*t;
 32 }
 33 double xmult(point p1,point p2,point p0) {
 34     return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
 35 }
 36 double disptoseg(point p,point l1,point l2) {
 37     point t=p;
 38     t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
 39     if (xmult(l1,t,p)*xmult(l2,t,p)>eps) return Distance(p,l1)<Distance(p,l2)?Distance(p,l1):Distance(p,l2);
 40     return fabs(xmult(p,l1,l2))/Distance(l1,l2);
 41 }
 42 point ptoseg(point p,point l1,point l2) {
 43     point t=p;
 44     t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
 45     if (xmult(l1,t,p)*xmult(l2,t,p)>eps) return Distance(p,l1)<Distance(p,l2)?l1:l2;
 46     return intersection(p,t,l1,l2);
 47 }
 48 double jiaotoju(point pp) {
 49     double res=inf;
 50     for(int i=0; i<4; i++) {
 51         res=min(res,disptoseg(pp,p[i],p[i+1]));
 52     }
 53     return res;
 54 }
 55 int main() {
 56     double r,x1,x2,y1,y2;
 57     while(~scanf("%lf%lf",&s.x,&s.y),s.x!=0||s.y!=0) {
 58         scanf("%lf%lf%lf",&c.x,&c.y,&r);
 59         scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 60         if(x1>x2) swap(x1,x2);
 61         if(y1>y2) swap(y1,y2);
 62         p[0].x=x1;
 63         p[0].y=y1;
 64         p[1].x=x2;
 65         p[1].y=y1;
 66         p[2].x=x2;
 67         p[2].y=y2;
 68         p[3].x=x1;
 69         p[3].y=y2;
 70         p[4]=p[0];
 71         double afa,tanafa;///起点到圆心的直线与x轴夹角,就是直线斜率
 72         if(fabs(s.x-c.x)<eps) {
 73             afa=90*pi/180;
 74         } else {
 75             tanafa=(s.y-c.y)/(s.x-c.x);
 76             afa=atan(tanafa);
 77         }
 78         double xita,sinxita;///起点到圆心的直线与切线夹角
 79         sinxita=r/Distance(s,c);
 80         xita=asin(sinxita);
 81         double bigxita=xita;
 82         double add=bigxita/1000;
 83         double delx,dely,dist1,dist2;
 84         point L2,J1,J2,center;
 85         double ans=inf,sum;
 86         for(double x=0; x<=bigxita; x+=add) {
 87             xita=x+afa;
 88             delx=10;
 89             dely=tan(xita)*delx;
 90             L2.x=s.x+delx;
 91             L2.y=s.y+dely;
 92             intersection_line_circle(c,r,s,L2,J1,J2);
 93             dist1=Distance(s,J1);
 94             dist2=Distance(s,J2);
 95             if(dist1>dist2) {
 96                 swap(dist1,dist2);
 97                 swap(J1,J2);
 98             }
 99             ans=min(ans,dist1+jiaotoju(J1));
100             center=ptoseg(J1,s,c);
101             J2.x=2*center.x-J1.x;
102             J2.y=2*center.y-J1.y;
103             ans=min(ans,dist1+jiaotoju(J2));
104         }
105         printf("%.2f
",ans);
106     }
107     return 0;
108 }
View Code

 事实上从上面的枚举可以看出,正解只有一个,并且一定在α-θ到α+θ之间。并且偏离正解越远,肯定距离越长,那么就是一个开口向上的二次函数,就可以对这个区间三分查找。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<algorithm>
  4 using namespace std;
  5 const double eps=1e-8;
  6 const double pi=acos(-1.0);
  7 const int inf=0x3f3f3f3f;
  8 struct point {
  9     double x,y;
 10 } s,c,p[8]; ///起点,圆心,矩形
 11 double Distance(point p1,point p2) {
 12     return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
 13 }
 14 point intersection(point u1,point u2,point v1,point v2) {
 15     point ret=u1;
 16     double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x)) /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
 17     ret.x+=(u2.x-u1.x)*t;
 18     ret.y+=(u2.y-u1.y)*t;
 19     return ret;
 20 }
 21 void intersection_line_circle(point c,double r,point l1,point l2,point& p1,point& p2) {
 22     point p=c;
 23     double t;
 24     p.x+=l1.y-l2.y;
 25     p.y+=l2.x-l1.x;
 26     p=intersection(p,c,l1,l2);
 27     t=sqrt(r*r-Distance(p,c)*Distance(p,c))/Distance(l1,l2);
 28     p1.x=p.x+(l2.x-l1.x)*t;
 29     p1.y=p.y+(l2.y-l1.y)*t;
 30     p2.x=p.x-(l2.x-l1.x)*t;
 31     p2.y=p.y-(l2.y-l1.y)*t;
 32 }
 33 double xmult(point p1,point p2,point p0) {
 34     return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
 35 }
 36 double disptoseg(point p,point l1,point l2) {
 37     point t=p;
 38     t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
 39     if (xmult(l1,t,p)*xmult(l2,t,p)>eps) return Distance(p,l1)<Distance(p,l2)?Distance(p,l1):Distance(p,l2);
 40     return fabs(xmult(p,l1,l2))/Distance(l1,l2);
 41 }
 42 point ptoseg(point p,point l1,point l2) {
 43     point t=p;
 44     t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
 45     if (xmult(l1,t,p)*xmult(l2,t,p)>eps) return Distance(p,l1)<Distance(p,l2)?l1:l2;
 46     return intersection(p,t,l1,l2);
 47 }
 48 double jiaotoju(point pp) {
 49     double res=inf;
 50     for(int i=0; i<4; i++) {
 51         res=min(res,disptoseg(pp,p[i],p[i+1]));
 52     }
 53     return res;
 54 }
 55 double r;
 56 double f(double xita) {
 57     double delx,dely,dist1,dist2;
 58     point L2,J1,J2,center;
 59     delx=10;
 60     dely=tan(xita)*delx;
 61     L2.x=s.x+delx;
 62     L2.y=s.y+dely;
 63     intersection_line_circle(c,r,s,L2,J1,J2);
 64     dist1=Distance(s,J1);
 65     dist2=Distance(s,J2);
 66     if(dist1>dist2) {
 67         swap(dist1,dist2);
 68         swap(J1,J2);
 69     }
 70     double res=dist1+jiaotoju(J1);
 71     center=ptoseg(J1,s,c);
 72     J2.x=2*center.x-J1.x;
 73     J2.y=2*center.y-J1.y;
 74     res=min(res,dist1+jiaotoju(J2));
 75     return res;
 76 }
 77 double TernarySearch(double L,double R) { /// 三分查找
 78     while(R-L>eps) {
 79         double LL=(L*2+R)/3;
 80         double RR=(L+R*2)/3;
 81         if(f(LL)<f(RR))  ///f为对应的值  这里求最小值
 82             R=RR;
 83         else
 84             L=LL;
 85     }
 86     return L;
 87 }
 88 int main() {
 89     double x1,x2,y1,y2;
 90     while(~scanf("%lf%lf",&s.x,&s.y),s.x!=0||s.y!=0) {
 91         scanf("%lf%lf%lf",&c.x,&c.y,&r);
 92         scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 93         if(x1>x2) swap(x1,x2);
 94         if(y1>y2) swap(y1,y2);
 95         p[0].x=x1;
 96         p[0].y=y1;
 97         p[1].x=x2;
 98         p[1].y=y1;
 99         p[2].x=x2;
100         p[2].y=y2;
101         p[3].x=x1;
102         p[3].y=y2;
103         p[4]=p[0];
104         double afa,tanafa;///起点到圆心的直线与x轴夹角,就是直线斜率
105         if(fabs(s.x-c.x)<eps) {
106             afa=90*pi/180;
107         } else {
108             tanafa=(s.y-c.y)/(s.x-c.x);
109             afa=atan(tanafa);
110         }
111         double xita,sinxita;///起点到圆心的直线与切线夹角
112         sinxita=r/Distance(s,c);
113         xita=asin(sinxita);
114         double ans=TernarySearch(afa-xita,afa+xita);
115         printf("%.2f
",f(ans));
116     }
117     return 0;
118 }
View Code

Shoot the Airplane http://acm.hdu.edu.cn/showproblem.php?pid=4458

题意:子弹竖直上抛运动,多边形水平匀速运动。问是否能有一个时间点使得子弹在多边形内。

暴力枚举时间,有了时间就知道子弹的位置和多边形的位置,然后判断点在多边形内就行。注意边上的不算。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 const double eps=1e-8;
 4 struct point{
 5     double x,y;
 6 }p[32],now[32],s;
 7 class PolygonJudge { //任意多边形判定
 8 #define zero(x) (((x)>0?(x):-(x))<eps)
 9     double xmult(point p1,point p2,point p0) {
10         return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
11     }
12 public:
13     int inside_polygon(point q,int n,point p[],int on_edge=1) {//判点在任意多边形内,顶点按顺时针或逆时针给出
14         point q2;
15         const int offset=100;//on_edge表示点在多边形边上时的返回值,offset为多边形坐标上限
16         int i=0,cnt;
17         while (i<n)
18             for (cnt=i=0,q2.x=rand()+offset,q2.y=rand()+offset; i<n; i++)
19                 if(zero(xmult(q,p[i],p[(i+1)%n]))&&(p[i].x-q.x)*(p[(i+1)%n].x-q.x)<eps&&(p[i].y-q.y)*(p[(i+1)%n].y-q.y)<eps)
20                     return on_edge;
21                 else if (zero(xmult(q,q2,p[i])))
22                     break;
23                 else if (xmult(q,p[i],q2)*xmult(q,p[(i+1)%n],q2)<-eps&&xmult(p[i],q,p[(i+1)%n])*xmult(p[i],q2,p[(i+1)%n])<-eps)
24                     cnt++;
25         return cnt&1;
26     }
27 } gx;
28 int main(){
29     int v,b,g,n;
30     while(~scanf("%d%d%d",&v,&b,&g),v|b|g){
31         scanf("%d",&n);
32         for(int i=0;i<n;i++){
33             scanf("%lf%lf",&p[i].x,&p[i].y);
34         }
35         double bigt;
36         if(g){
37             bigt=2.0*b/g;
38         }
39         else{
40             bigt=120.0/b;
41         }
42         double add=bigt/10000;
43         bool flag=false;
44         double ans;
45         for(double t=0;t<=bigt;t+=add){
46             s.x=0;
47             s.y=b*t-0.5*g*t*t;
48             for(int i=0;i<n;i++){
49                 now[i]=p[i];
50                 now[i].x+=v*t;
51             }
52             if(gx.inside_polygon(s,n,now,0)){
53                 flag=true;
54                 ans=t;
55                 break;
56             }
57         }
58         if(!flag) puts("Miss!");
59         else{
60             printf("%.2f
",ans);
61         }
62     }
63     return 0;
64 }
View Code

还有一种解法,相对运动的思想,多边形向左运动,相当于多边形不动,子弹向右有一样的速度,那么子弹就是个抛物线,求抛物线是否进入多边形内。至今没敲出来,先放一放。

end

原文地址:https://www.cnblogs.com/gaolzzxin/p/3947987.html