田忌赛马是个很古老的问题了。
首先回顾一下这个故事。
齐使者如梁,孙膑以刑徒阴见,说齐使。齐使以为奇,窃载与之齐。齐将田忌善而客待之。忌数与齐诸公子驰逐重射。孙子见其马足不甚相远,马有上、中、下辈。于是孙子谓田忌曰:“君弟重射,臣能令君胜。”田忌信然之,与王及诸公子逐射千金。及临质,孙子曰:“今以君之下驷与彼上驷,取君上驷与彼中驷,取君中驷与彼下驷。”既驰三辈毕,而田忌一不胜而再胜,卒得王千金。于是忌进孙子于威王。威王问兵法,遂以为师。
现在请你思考,如果双方马匹数为K,分成K个等级,田忌的马比齐王同等级的马慢,而且比齐王低等级的马快。赛马双方的出场顺序不定,田忌取胜的概率有多大?
输入
第一行一个数N,表示下面有N个测试数据。
紧接着下面N行,每行一个整数K ( 1 <= K <= 10 )
输出
对于每个输入K, 输出田忌取胜的概率,精确到小数点后3位。 每个输出占一行。
解决方法:全排列,比如各有5匹马,我们把齐王的马的出场顺序定位1 2 3 4 5,而田忌的马则有5!种出场顺序,排列出来开所有排列中能有多少种能取胜,则能算出概率。我的代为:
(貌似还有很多更强大的算法,欢迎大家讨论)
#include<stdio.h>
int main(void)
{
int n,m,a[15],i,j,t,h;
int test;
int sum,sum2;
double gailu;
long s=0;
scanf("%d",&test);
while(test--)
{
scanf("%d",&n);
sum2=1;
for(h=1;h<=n;h++)
{
sum2*=h;
}
i=1;
a[i]=1;
m=0;
while(1)
{
t=1;
for(j=1;j<i;j++)
{
if(a[j]==a[i])
{
t=0;
break;
}
}
if(t&&i==n)
{
sum=0;
for(j=1;j<=n;j++)
{
if(a[j]>j)
{
sum++;
}
}
if(sum>n/2) m++;
}
if(t&&i<n)
{
i++;
a[i]=1;
continue;
}
while(a[i]==n)
{
i--;
}
if(i>0) a[i]++;
else
break;
}
gailu=(double)m/sum2;k.,j//.,
printf("%0.3lf\n",gailu);
}
return 0;
}