Can you find it? HDU2141
题目好理解:在输入的三行数据中(必须每行取一个数)相加与输入的值比较。
如果用暴力肯定会超时的:那么把俩行合并,再二分。。。
1 #include<iostream> 2 #include<stdio.h> 3 #include<math.h> 4 #include<algorithm> 5 using namespace std; 6 int ab[501*501]; 7 int dis(int h,int q)//二分查找 8 { 9 int left,right,mid; 10 left=0; 11 right=h-1; 12 while(left<=right) 13 { 14 mid=(left+right)/2; 15 if(ab[mid]==q) 16 return 1; 17 else if(ab[mid]>q) 18 right=mid-1; 19 else if(ab[mid]<q) 20 left=mid+1; 21 } 22 return 0; 23 } 24 int main() 25 { 26 int cout1=1,l,m,n,a[505],b[505],c[505],i,j,h,t,d,s,q; 27 while(scanf("%d%d%d",&l,&m,&n)!=EOF) 28 { 29 h=0; 30 for(i=0;i<l;i++) 31 scanf("%d",&a[i]); 32 for(i=0;i<m;i++) 33 scanf("%d",&b[i]); 34 for(i=0;i<n;i++) 35 scanf("%d",&c[i]); 36 for(i=0;i<l;i++) 37 for(j=0;j<m;j++) 38 ab[h++]=a[i]+b[j];//合并 39 sort(ab,ab+h); 40 scanf("%d",&t); 41 printf("Case %d: ",cout1++); 42 for(i=0;i<t;i++) 43 { 44 d=0; 45 scanf("%d",&s); 46 for(j=0;j<n;j++) 47 { 48 q=s-c[j]; 49 if(dis(h,q)) 50 { 51 d=1; 52 break; 53 } 54 } 55 if(d==0) 56 printf("NO "); 57 else if(d==1) 58 printf("YES "); 59 } 60 } 61 return 0; 62 }
Toxophily HDU2298
首先这是一个物理题!!(全忘记了)
再次他们是在一个平面里的!!
先是用纯粹的物理思想来做;
由x=v*cos(θ)*t,y=v*sin(θ)*t-g*t*t/2,然后通过数学变形(sin(θ)^2+cos(θ)^2=1)得到方程:
g*x*x*tan(θ)^2-2*v*v*x*tan(θ)+2*v*v*y+g*x*x=0,再用求根公式解该一元二次方程。(1+tan^2(α)=sec^2(α), cosα ·secα=1)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 5 using namespace std; 6 const double PI=acos(-1.0); 7 const double g=9.8; 8 9 int main() 10 { 11 int t; 12 double x,y,v; 13 double a,b,c,d,p1,p2; 14 cin>>t; 15 while(t--) 16 { 17 cin>>x>>y>>v; 18 a=g*x*x; 19 b=-2*v*v*x; 20 c=2*v*v*y+g*x*x; 21 d=b*b-4*a*c; 22 if(d<0) 23 { 24 printf("-1 "); 25 continue; 26 } 27 p1=atan((-b+sqrt(d))/a/2); 28 p2=atan((-b-sqrt(d))/a/2); 29 if((p1<0||p1>PI/2)&&(p2<0||p2>PI/2)) 30 printf("-1 "); 31 else if(p1<0||p1>PI/2) 32 printf("%.6lf ",p2); 33 else if(p2<0||p2>PI/2) 34 printf("%.6lf ",p1); 35 else 36 printf("%.6lf ",min(p1,p2)); 37 } 38 return 0; 39 }
之后方法参照:http://blog.csdn.net/hello_there/article/details/8519008
Party All the Time HDU4355
一道典型的三分题:
1 #include<iostream> 2 #include<algorithm> 3 #include<stdio.h> 4 #include<math.h> 5 using namespace std; 6 int n; 7 struct line 8 { 9 double bumanyi; 10 double area; 11 }a[50000]; 12 bool comp1(line x,line y) 13 { 14 return x.area<y.area; 15 } 16 double dis(double mid) 17 { 18 int i; 19 double t; 20 t=0; 21 for(i=0;i<n;i++) 22 { 23 t+=fabs((a[i].area-mid)*(a[i].area-mid)*(a[i].area-mid))*a[i].bumanyi; 24 } 25 return t; 26 } 27 int main() 28 { 29 double mid,mmid,left,right,t1,t2; 30 int t,i,w=0; 31 scanf("%d",&t); 32 while(t--) 33 { 34 w++; 35 scanf("%d",&n); 36 for(i=0;i<n;i++) 37 scanf("%lf %lf",&a[i].area,&a[i].bumanyi); 38 sort(a,a+n,comp1); 39 left=a[0].area;right=a[n-1].area; 40 while(right-left>1e-4)//因为结果取整,精度不要太大,会超时的 41 { 42 mid=left/2+right/2; 43 mmid=mid/2+right/2; 44 t1=dis(mid); 45 t2=dis(mmid); 46 if(t1>t2) 47 left=mid; 48 else if(t1<t2) 49 right=mmid; 50 else 51 break; 52 53 } 54 printf("Case #%d: %.lf ",w,t1); 55 } 56 return 0; 57 }
Squares POJ2002
算法过程:
1 将顶点按x坐标递增排序,若x相同,按y坐标递增排序,然后枚举所有边,对每一条由点p1和p2(根据排序p1 < p2)组成的边按照如下方式可唯一确定一个正方形:
1) 将边绕p1逆时针旋转90度得到点p3
2) 将边绕p2顺时针旋转90度得到点p4
则p1 p2 p3 p4组成一个正方形,设p1 = (x1,y1), p2 = (x2, y2),根据向量的旋转公式可以求出p3, p4的坐标为
p3 = (y1 - y2 + x1, x2 - x1 + y1)
p4 = (y1 - y2 + x2, x2 - x1 + y2)
2 然后搜索点p3和p4是否存在,若存在则找到一个正方形,计数加1,可以发现总是存在两条边确定的正方形是一样的,也就是说每个正方形会被发现2次,所以要将最后的计数结果除以2.
实现的时候关键是如何搜索某个点是否存在,由于所有点都排序过,所以可以用二分查找来搜索,但速度比较慢,至少1000ms, hash的速度更快些,可以达到几百ms,还有hash表如果用开放地址线性探测法解决冲突的话,很容易超时,
而用链地址法解决冲突效果要好很多。下面是二分搜索和hash两种方法的代码实现。
貌似那些会超时的程序可以用二分法或三分法来压缩时间(个人猜测!!)
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int n; 6 struct line 7 { 8 int x; 9 int y; 10 }a[1005]; 11 bool comp1(line i,line j) 12 { 13 if(i.x<j.x) 14 return true; 15 else if(i.x==j.x) 16 { 17 if(i.y<j.y) 18 return true; 19 } 20 return false; 21 } 22 int chazhao(int i,int j) 23 { 24 int left,right,mid; 25 left=0; 26 right=n-1; 27 while(left<=right) 28 { 29 mid=(left+right)/2; 30 if(i==a[mid].x&&j==a[mid].y) 31 return 1; 32 else if(i<a[mid].x||(i==a[mid].x&&j<a[mid].y)) 33 right=mid-1; 34 else 35 left=mid+1; 36 } 37 return 0; 38 } 39 int main() 40 { 41 int sum,i,j,x,y; 42 while(scanf("%d",&n)!=EOF) 43 { 44 if(n==0) 45 break; 46 sum=0; 47 for(i=0;i<n;i++) 48 scanf("%d %d",&a[i].x,&a[i].y); 49 sort(a,a+n,comp1);//排序 50 for(i=0;i<n;i++) 51 for(j=i+1;j<n;j++) 52 { 53 x=a[i].y-a[j].y+a[i].x; 54 y=a[j].x-a[i].x+a[i].y; 55 if(chazhao(x,y)==0) 56 continue; 57 x=a[i].y-a[j].y+a[j].x; 58 y=a[j].x-a[i].x+a[j].y; 59 if(chazhao(x,y)) 60 sum++; 61 } 62 printf("%d ",sum/2); 63 } 64 return 0; 65 }//从前俩个点来判断第三第四个点是否存在