题目描述如下:
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
今有 100100 根绳子,当然会有 200200 个绳头。
如果任意取绳头两两配对,把所有绳头都打结连接起来。最后会形成若干个绳圈(不考虑是否套在一起)。
我们的问题是:请计算最后将形成多少个绳圈的概率最大?
运行限制
最大运行时间:1s
最大运行内存: 128M
蓝桥云课给题目打的tag是简单,但是题目的通过率却只有百分之十,可以看出题目难度还是蛮高滴。
不要被简单
两个字骗了!!
这道题是典型的动态规划题目,寻找递推关系即可。
计算概率,先寻找,i个绳子可以有多少种打结方式。
设i-1根绳子有sum[i-1]种打结方式,则可得:
如图所示,i根绳子有sum[i-1]*(2i-1)种打结方式。
再计算,如有i根绳子,打结成x个圈有几种打结方式,递推方式如下表:
此时,根据此递推关系,即可得出i根绳子,形成每种圈数的打结方式数量,将打结方式除以i根绳子的打结方式总数量,即可的带该圈数形成的概率,寻找概率最高者即得题目答案。
或者直接寻找不同圈数打结方式数量的最大值,拥有最大值者即概率最大者。
Java代码如下:
import java.util.*;
public class Sj {
public static void main(String[] args) {
//计算100个绳子可以生成多少种打结方式
double[] sum = new double[101];
sum[1] = 1;
for (int i = 2; i < sum.length; i++) {
sum[i] = sum[i-1] * (2*i - 1);
}
double countOf100 = sum[100];//100个绳子可以进行的打结方式数量
double[][] c = new double[101][101];
c[1][1] = 1;//递推空间初始化
for (int i = 2; i < 101; i++) {
for (int j = 1; j < i + 1; j++) {
if (j == 1){
c[i][j] = c[i-1][j] * (i - 1) * 2;
continue;
}
if (j == i){
c[i][j] = 1;
continue;
}
c[i][j] = c[i-1][j-1] + c[i-1][j] * (i-1) * 2;
}
//System.out.println("第" + i + "根绳子 " + Arrays.toString(c[i]));
}
//c[100]中即每种圈数的打结方式数量
/*对c[100]进行排序*/
Map<Integer,Double> map = new HashMap<>();
for (int i = 1; i < 101; i++) {
map.put(i, c[100][i]);
}
Comparator<Map.Entry<Integer, Double>> comparator = new Comparator<Map.Entry<Integer, Double>>() {
@Override
public int compare(Map.Entry<Integer, Double> o1, Map.Entry<Integer, Double> o2) {
return (int) (o1.getValue() - o2.getValue());
}
};
Set<Map.Entry<Integer,Double>> sort = new TreeSet<>(comparator);
for (Map.Entry<Integer, Double> entry : map.entrySet()) {
sort.add(entry);
}
for (Map.Entry<Integer, Double> entry: sort){
System.out.println(entry.getKey() + " is " + entry.getValue());
}
}
}
结果如下:
即,形成3圈的概率最大。