[International readers should note that some words are puns on cows.]
Having made a fortune on Playbov magazine, Hugh Heifer has moved from his original field in the country to a fashionable yard in the suburbs. To visit fond pastoral memories, he wishes to cowmmute back to his old stomping grounds. Being environmentally minded, Hugh wishes to transport himself using his own power on a Cowcycle (a bicycle specially fitted for his neatly manicured hooves).
Hugh weighs over a ton; as such, getting smoothly up to speed on traditional cowcycle gear sets is a bit challenging. Changing among some of the widely spaced gear ratios causes exertion that‘s hard on Hugh‘s heart.
Help Hugh outfit his Cowcycle by choosing F (1 <= F <= 5) gears (sprockets) in the front and R (1 <= R <= 10) gears in the rear of his F*R speed cowcycle subject to these rules:
Calculate the mean and variance of a set of differences (xi in this formula) by the following formulae:
Deduce and print the optimal sets of F front gears and R rear gears so that the variance is minimized (and the ratios span a factor of at least 3x).
The first line contains F and R, the numbers of front and rear gears. The second line contains four numbers: F1, F2 (25 <= F1 < F2 <= 80), R1, and R2 (5 <= R1 < R2 <= 40). All front gears from F1 through F2 are available; all rear gears from R1 through R2 are available. There will exist at least one legal set of gears.
2 5 39 62 12 28
Display the number of teeth on the set of F chosen front gears, from smallest to largest, on the first line of output (separated by spaces). Display the number of teeth on the set of R chosen rear gears, from smallest to largest, on the second line of output. All gears have an integer number of teeth, of course.
If multiple optimal answers exist, output the answer with the smallest front gear set (smallest first gear, or smallest second gear if first gears match, etc.). Likewise, if all first gears match, output the answer with the smallest rear gear set (similar rules to the front gear set).
39 53 12 13 15 23 27
The challenge in this problem is "reading the problem". Don‘t read further if you are working on that level of challenge. If the problem is just completely unclear to you, read in.
The problem wants you to find "an optimal set of gear ratios" such that the spacing between the ratios is most uniform. Consider the test case above:
2 5 39 62 12 28This specifies two front gears from the set 39..62; five rear gears from the set 12..28. The program must examine all possible pairs of 62-39+1=24 front gears and all possible quintuples from 28-12+1=17 rear gears. Combinatorically, The total number of possibilities is (24 take 2) times (17 take 5), which is 24!/22!/2! x 17!/5!/12! which is 656,880 possibilities (I think).
For each of these possibilities, calculations like the following. This example considers in some sense the "first" case: front gears of 39 and 40, rear gears of 12, 13, 14, 15, and 16.
First, calculate all the possible ratios:
39/12 = 3.25000000000000000000 39/13 = 3.00000000000000000000 39/14 = 2.78571428571428571428 39/15 = 2.60000000000000000000 39/16 = 2.43750000000000000000 40/12 = 3.33333333333333333333 40/13 = 3.07692307692307692307 40/14 = 2.85714285714285714285 40/15 = 2.66666666666666666666 40/16 = 2.50000000000000000000
Then, sort them:
39/16 = 2.43750000000000000000 40/16 = 2.50000000000000000000 39/15 = 2.60000000000000000000 40/15 = 2.66666666666666666666 39/14 = 2.78571428571428571428 40/14 = 2.85714285714285714285 39/13 = 3.00000000000000000000 40/13 = 3.07692307692307692307 39/12 = 3.25000000000000000000 40/12 = 3.33333333333333333333
Then, calculate the absolute value of the differences:
2.43750000000000000000 - 2.50000000000000000000 = 0.06250000000000000000 2.50000000000000000000 - 2.60000000000000000000 = 0.10000000000000000000 2.60000000000000000000 - 2.66666666666666666666 = 0.06666666666666666666 2.66666666666666666666 - 2.78571428571428571428 = 0.11904761904761904762 2.78571428571428571428 - 2.85714285714285714285 = 0.07142857142857142857 2.85714285714285714285 - 3.00000000000000000000 = 0.14285714285714285715 3.00000000000000000000 - 3.07692307692307692307 = 0.07692307692307692307 3.07692307692307692307 - 3.25000000000000000000 = 0.17307692307692307693 3.25000000000000000000 - 3.33333333333333333333 = 0.08333333333333333333
Then, calculate the mean and variance of the set of numbers on the right, above. The mean is (I think): 0.0995370370370370370366666. The variance is approximately 0.00129798488416722.
Of course this set of gears is not valid, since it does not have a 3x span from highest gear to lowest.
Find the set of gears that minimizes the variance and has a 3x or greater span.
这道题乍一看把我吓了一跳。根据极限数据:C(56,5)*C(36,10)=9.7*10^14。不算排序就已经严重超时了!但是我还是抱着做做看的思路,直接深搜枚举所有情况并记录。由于我对常数的管理,使搜索的效率大大提高。
剪枝和优化:①如果小于三倍就可以直接退出,没必要算下去了。公式原来是:a[f]/b[1]<3*a[1]/b[f],但是由于乘法比除法快很多,我们可以化成a[f]*b[f]<3*a[1]*b[1]。
②求方差时,因为排过序,不必像解释的那样取绝对值,而是大的减小的。
③省掉不必要的函数。我果断把搜完后判断的处理和后齿轮的枚举放在了一起(inline的别说)
④在枚举齿轮的时候,没有用那种flag数组的记录,而是直接加一个参数直接循环。
。代码:
/* PROG:cowcycle ID:juan1973 LANG:C++ */ #include<stdio.h> using namespace std; int a[57],b[37],ansa[57],ansb[37],f,r,f1,r1,f2,r2,i,cnt; double sum,tot,ans,c[2017],t; void find_r(int k,int step) { int i,j; if (step==r+1) { if (a[f]*b[r]<3*a[1]*b[1]) return; //if (a[f]/b[1]<3*a[1]/b[r]) cnt=0; sum=tot=0; for (i=1;i<=f;i++) for (j=1;j<=r;j++) c[++cnt]=double(a[i])/double(b[j]); for (i=1;i<cnt;i++) for (j=i+1;j<=cnt;j++) if (c[i]>c[j]) {t=c[i];c[i]=c[j];c[j]=t;} for (i=1;i<cnt;i++){c[i]=c[i+1]-c[i];sum+=c[i];} sum/=--cnt; for (i=1;i<=cnt;i++) tot+=(c[i]-sum)*(c[i]-sum); if (tot<ans) { ans=tot; for (i=1;i<=f;i++) ansa[i]=a[i]; for (i=1;i<=r;i++) ansb[i]=b[i]; } return; } for (i=k;i<=r2-r+step;i++) { b[step]=i; find_r(i+1,step+1); } } void find_f(int k,int step) { if (step==f+1){find_r(r1,1);return;} for (int i=k;i<=f2-f+step;i++) { a[step]=i; find_f(i+1,step+1); } } int main() { freopen("cowcycle.in","r",stdin); freopen("cowcycle.out","w",stdout); scanf("%ld%ld",&f,&r); scanf("%ld%ld%ld%ld",&f1,&f2,&r1,&r2); ans=99999999; find_f(f1,1); for (i=1;i<f;i++) printf("%ld ",ansa[i]);printf("%ld\n",ansa[f]); for (i=1;i<r;i++) printf("%ld ",ansb[i]);printf("%ld\n",ansb[r]); //scanf("%ld%ld",&f,&r); return 0; }
usaco training 4.2.4 Cowcycles 题解,布布扣,bubuko.com
usaco training 4.2.4 Cowcycles 题解
原文:http://blog.csdn.net/jiangshibiao/article/details/20000311