网站:csust训练3
A 三分的题目,给出灯高,人高,以及和墙的距离,求最长的影子长度。 Light Bulb ZOJ 3203
本来我是三分角度,角度[0,atan(H/D)],测试数据都是对的,但是WA了,我到现在还是不知道为什么........
后来是三分投在墙上的影子长度,[0,h],投在墙上的影子最多是h。
代码: 0MS
1 #include <stdio.h> 2 #include <iostream> 3 #include <math.h> 4 using namespace std; 5 int main() 6 { 7 double H,h,D,l,r,mid,midd,l1,l2; 8 int T; 9 scanf("%d",&T); 10 while (T--) 11 { 12 scanf("%lf%lf%lf",&H,&h,&D); 13 r=h; 14 l=0; 15 while(r-l>1e-9) 16 { 17 mid=(l+r)/2; 18 midd=(mid+r)/2; 19 l1=mid+D*(h-mid)/(H-mid); 20 l2=midd+D*(h-midd)/(H-midd); 21 if(l1<l2) 22 l=mid; 23 else 24 r=midd; 25 } 26 printf("%.3lf\n",l2); 27 } 28 return 0; 29 }
这道题还有个数学方法,直接求峰值,详情见:http://blog.csdn.net/freezhanacmore/article/details/9887115 (表示膜拜,用数学方法的都膜拜)
B 求最长回文子串的长度,如果暴力0(n^2)果断超时,要用Manacher算法。
优化原因见: http://www.2cto.com/kf/201210/164253.html
代码: 360 ms/15000ms 10936kb/65536kb 这道题的时间限制真长......从没做过15s的题Orz
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 #define N 1000008 6 char str[N], str1[N<<1]; 7 int p[N<<1]; 8 int maxx; 9 void Manacher() 10 { 11 int i, j, mx, id; 12 memset(str1, '#', sizeof(str1)); 13 memset(p, 0, sizeof(p)); 14 for(i=0; str[i]!='\0'; i++) 15 str1[(i+1)<<1]=str[i]; //把字符插入到#####中 16 str1[(i+1)<<1]='\0'; 17 mx=0; 18 maxx=0; 19 for(i=1; str1[i]!='\0'; i++) 20 { 21 if( mx>i ) 22 p[i]=min(mx-i, p[id*2-i]); //见:http://www.cnblogs.com/lv-2012/archive/2012/11/15/2772268.html PS:没有这一步会超时 23 else 24 p[i]=1; 25 while( str1[i-p[i]]==str1[i+p[i]] ) //拓展半径 26 p[i]++; 27 if( i+p[i]>mx )//mx代表当前回文串扩展的最大距离 28 { 29 mx=i+p[i]; 30 id=i; 31 } 32 if( p[i]-1>maxx ) 33 maxx=p[i]-1; //更新最长长度 34 } 35 } 36 int main() 37 { 38 int Case=0; 39 while( scanf("%s", str) && strcmp(str, "END")!=0 ) //str!=END 40 { 41 maxx=0; 42 Manacher(); 43 printf("Case %d: %d\n",++Case,maxx); 44 } 45 }
C Minimum Inversion Number HDU 1394 大意是给n个数,分别是0~n-1,前面的数比后面的数大的数对有多少个,算好之后把第一个数移到最后,又算.......最后求最小的数对是多少个。此题用线段树做,但是我还没看线段树,过一阵再补上,先讲下不用线段树的做法。
代码 : 265ms
1 #include <stdio.h> 2 #include <iostream> 3 using namespcae std; 4 int main() 5 { 6 int n,i,j,sum,minn,sum1 7 while(~scanf("%d",&n)) 8 { 9 sum=0; 10 for(i=0;i<n;i++) 11 scanf("%d",&a[i]); 12 for(i=0;i<n-1;i++) 13 for(j=i+1;j<n;j++) 14 if(a[i]>a[j]) 15 sum++; //求出初数列的个数 16 minn=sum; //初始化最小值 17 for(i=1;i<n;i++) 18 { 19 sum1=sum+n-1-2*a[i]; //sum1=sum(上一个数列的值)+(n-1-a[i])(移到后面的那个数和最大数的差值)-a[i](比a[i]小的数的个数) 20 if(minn>sum1) 21 minn=sum1; //更新最小值 22 sum=sum1; //更新上一个数列的值 23 } 24 printf("%d\n",minn); 25 } 26 return 0; 27 }
代码: 0MS ,注意不能用while,用do....while,因为至少要执行一次,算AB,CD 间的距离
1 #include<stdio.h> 2 #include<iostream> 3 #include<math.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<string.h> 7 using namespace std; 8 struct point 9 { 10 double x,y; 11 }; 12 double dis(point a,point b) 13 { 14 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); //求两点间距离 15 } 16 double p,q,r; 17 double find2(point a,point c,point d)//三分CD 18 { 19 point left,right; 20 point mid,midmid; 21 double t1,t2; 22 left=c; 23 right=d; 24 do 25 { 26 mid.x=(left.x+right.x)/2; 27 mid.y=(left.y+right.y)/2; 28 midmid.x=(mid.x+right.x)/2; 29 midmid.y=(mid.y+right.y)/2; 30 t1=dis(a,mid)/r+dis(mid,d)/q; 31 t2=dis(a,midmid)/r+dis(midmid,d)/q; //ids(a,mid)是求AB,CD间的距离 32 if(t1>t2) 33 left=mid; 34 else 35 right=midmid; 36 }while(dis(left,right)>1e-5); 37 return t2; 38 } 39 double find(point a,point b,point c,point d) //三分AB 40 { 41 point left,right; 42 point mid,midmid; 43 double t1,t2; 44 left=a; 45 right=b; 46 do 47 { 48 mid.x=(left.x+right.x)/2; 49 mid.y=(left.y+right.y)/2; 50 midmid.x=(mid.x+right.x)/2; 51 midmid.y=(mid.y+right.y)/2; 52 t1=dis(a,mid)/p+find2(mid,c,d); 53 t2=dis(a,midmid)/p+find2(midmid,c,d); 54 if(t1>t2) 55 left=mid; 56 else 57 right=midmid; 58 }while(dis(left,right)>=1e-5); 59 return t2; 60 } 61 int main() 62 { 63 int T; 64 point a,b,c,d; 65 scanf("%d",&T); 66 while(T--) 67 { 68 scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y); 69 scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y); 70 scanf("%lf%lf%lf",&p,&q,&r); 71 printf("%.2lf\n",find(a,b,c,d)); 72 } 73 return 0; 74 }
代码: 0ms
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 using namespace std; 5 int a[105],b[105]; 6 int c1[10005],c2[10005]; 7 int main() 8 { 9 int n,m,i,j,k; 10 while(~scanf("%d%d",&n,&m)) 11 { 12 for(i=1;i<=n;i++) 13 scanf("%d%d",&a[i],&b[i]); 14 memset(c1,0,sizeof(c1)); 15 memset(c2,0,sizeof(c2)); 16 c1[0]=1; 17 for(i=1;i<=n;i++) 18 { 19 for(j=0;j<=m;j++) 20 for(k=a[i];j+k<=m&&k<=b[i];k++) 21 c2[j+k]+=c1[j]; 22 for(j=0;j<=m;j++) 23 c1[j]=c2[j]; 24 memset(c2,0,sizeof(c2)); 25 } 26 printf("%d\n",c1[m]); 27 } 28 return 0; 29 }