Chinaunix首页 | 论坛 | 博客
  • 博客访问: 622861
  • 博文数量: 79
  • 博客积分: 848
  • 博客等级: 军士长
  • 技术积分: 1800
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-26 19:30
文章分类

全部博文(79)

文章存档

2015年(4)

2013年(39)

2012年(36)

分类: C/C++

2012-10-25 15:00:51

前天晚上在寝室和室友卧聊的时候,他提出了这样一个问题:
假如假期之中父母给你安排了100个相亲的对象,你只能跟每个对象约会一次,约会的时候你可以选择表白也可以选择不表白,一旦表白了女方就会答应你的请求,然后相亲活动停止;假如没有表白对于这个对象来说你就没有机会了!在这样的条件下你用什么样的策略才能保证你能够以最大的概率找到你认为更好的女生捏?
乍一看貌似问题不是很难,但是仔细分析起来才发现不是很简单所以现在拿到这个地方跟大家讨论一下,还希望看看众位算法大牛的解释!
首先分析问题:你在跟每个相亲对象约会之前是不知道她的好坏的(当然这里仅限于第一印象的好坏,有点肤浅,:-))但是每个人你只有一次约会的机会,你在见完所有对象之前你永远不知道后面的相亲对象的情况,一旦决定表白了你就没有机会再见后面的相亲对象了,听起来真是十分的残酷呀!!可能有些人会选择我先把前面的99个都约会一遍,然后不管第一百个怎么样约会的时候直接表白,至少这样把每个人都看了一遍,死也死的没有遗憾了,呵呵开个玩笑。如果你是聪明人肯定不会选择这个策略的!
盯着相亲这个问题来说事,显然大家心思就跑偏了,要解决这个问题我们首先要对他进行建模,这100个相亲对象我们虽然没有见过她们,但是想必她们肯定是有个好坏之分的,所以我们可以把她们抽象成一个具有100个不同大小的元素的整型的数组a[100]。
现在有这样的一种策略,就是我可以先约会前n个对象,只约会不表白,回来之后我给这n个对象打个分,算一个平均值出来,然后在约会剩下的100-n个对象,当我碰到比这个平均值大的对象的时候我就向她表白!貌似这样的策略想来比起瞎找来要强许多,但是现在有个问题就出现了我们如何来确定这个n的大小捏?对的,我们可以写个程序琼举一下。那么怎么来设计这个程序捏,我想出了以下的一个方案:
首先我定义一个整型的数组ivec[100],用来存储着100个不同分值(分值的大小是从1-100之间随机出来的)的姑娘,然后循环求解n(1-100)的均值,并将在每个n值的情况下选出来的数值记录在另外一个数组cvec[100]之中,然后循环上述过程10000次,将每次对应与每个cvec[]元素的对象值,做和最后求平均值,输出,看一看到底n取多少的时候输出的平均值是最大的,这样就说明了n的最佳取值:

点击(此处)折叠或打开

  1. #include<iostream>
  2. #include<ctime>
  3. #include<cstdlib>
  4. #include<vector>
  5. #include<algorithm>
  6. using namespace std;
  7. int average(vector<int> &a, int b)
  8. {
  9.     int sum = 0;
  10.     for(int i= 0; i < b; i++)
  11.     {
  12.         sum += a[i];
  13.     }
  14.     return sum / b;
  15. }
  16. int main()
  17. {
  18.     vector<int> ivec;
  19.     vector<int> cvec;
  20.     int aver = 0;
  21.     int k = 1;
  22.     int j = 0;
  23.     for(int s = 1; s <= 100; s++)
  24.     {
  25.         ivec.push_back(s);
  26.         cvec.push_back(0);
  27.     }
  28.     while(k <= 10000)
  29.     {
  30.         srand(time(0));
  31.         random_shuffle(ivec.begin(), ivec.end());//将数组中的元素随机排列!
  32.         for(int i = 0; i < 100; i++)
  33.         {
  34.             aver = average(ivec,i+1);            //取前n个对象的平均值
  35.             for(j = i+1; j < 100; j++)
  36.             {
  37.                 if(ivec[j] > aver)
  38.                 {
  39.                     cvec[i] = cvec[i] + ivec[j]; //记录选择出来的数值
  40.                     break;
  41.                 }
  42.             }
  43.             if(j == 100)
  44.             {
  45.                 cvec[i] += ivec[j-1];
  46.             }
  47.         }
  48.         k++;
  49.     }
  50.     for(int h = 0; h < 100; h++)
  51.     {
  52.         cout << "the sample is " << h+1 << " the counter is: " << cvec[h]/10000 << endl;
  53.     }
  54.     return 0;
  55. }
执行结果:

点击(此处)折叠或打开

  1. the sample is 1 the counter is: 72.7971
  2. the sample is 2 the counter is: 73.2202
  3. the sample is 3 the counter is: 71.4259
  4. the sample is 4 the counter is: 75.0164
  5. the sample is 5 the counter is: 74.4297
  6. the sample is 6 the counter is: 76.3934
  7. the sample is 7 the counter is: 77.2789
  8. the sample is 8 the counter is: 77.635
  9. the sample is 9 the counter is: 76.9348
  10. the sample is 10 the counter is: 74.5057
  11. the sample is 11 the counter is: 73.8079
  12. the sample is 12 the counter is: 72.5249
  13. the sample is 13 the counter is: 75.5074
  14. the sample is 14 the counter is: 75.125
  15. the sample is 15 the counter is: 74.9676
  16. the sample is 16 the counter is: 75.6766
  17. the sample is 17 the counter is: 75.4921
  18. the sample is 18 the counter is: 76.3521
  19. the sample is 19 the counter is: 76.2931
  20. the sample is 20 the counter is: 75.9187
  21. the sample is 21 the counter is: 75.2278
  22. the sample is 22 the counter is: 74.449
  23. the sample is 23 the counter is: 73.0363
  24. the sample is 24 the counter is: 68.9686
  25. the sample is 25 the counter is: 69.9028
  26. the sample is 26 the counter is: 72.6237
  27. the sample is 27 the counter is: 69.613
  28. the sample is 28 the counter is: 71.4186
  29. the sample is 29 the counter is: 75.8713
  30. the sample is 30 the counter is: 74.4902
  31. the sample is 31 the counter is: 72.3863
  32. the sample is 32 the counter is: 77.3795
  33. the sample is 33 the counter is: 76.5902
  34. the sample is 34 the counter is: 77.7821
  35. the sample is 35 the counter is: 76.514
  36. the sample is 36 the counter is: 76.5334
  37. the sample is 37 the counter is: 76.2138
  38. the sample is 38 the counter is: 76.2427
  39. the sample is 39 the counter is: 75.2769
  40. the sample is 40 the counter is: 74.5672
  41. the sample is 41 the counter is: 74.2544
  42. the sample is 42 the counter is: 71.6644
  43. the sample is 43 the counter is: 76.5912
  44. the sample is 44 the counter is: 72.7051
  45. the sample is 45 the counter is: 68.3414
  46. the sample is 46 the counter is: 70.0941
  47. the sample is 47 the counter is: 75.0341
  48. the sample is 48 the counter is: 73.8389
  49. the sample is 49 the counter is: 71.382
  50. the sample is 50 the counter is: 76.3986
  51. the sample is 51 the counter is: 75.0583
  52. the sample is 52 the counter is: 71.8271
  53. the sample is 53 the counter is: 75.9133
  54. the sample is 54 the counter is: 76.451
  55. the sample is 55 the counter is: 76.2901
  56. the sample is 56 the counter is: 75.7828
  57. the sample is 57 the counter is: 74.8741
  58. the sample is 58 the counter is: 71.758
  59. the sample is 59 the counter is: 76.1354
  60. the sample is 60 the counter is: 76.4661
  61. the sample is 61 the counter is: 75.2136
  62. the sample is 62 the counter is: 71.2485
  63. the sample is 63 the counter is: 75.5339
  64. the sample is 64 the counter is: 74.6645
  65. the sample is 65 the counter is: 73.3281
  66. the sample is 66 the counter is: 69.7064
  67. the sample is 67 the counter is: 70.2078
  68. the sample is 68 the counter is: 73.6396
  69. the sample is 69 the counter is: 70
  70. the sample is 70 the counter is: 76.1401
  71. the sample is 71 the counter is: 74.1022
  72. the sample is 72 the counter is: 71.3195
  73. the sample is 73 the counter is: 75.7528
  74. the sample is 74 the counter is: 75.3652
  75. the sample is 75 the counter is: 72.6577
  76. the sample is 76 the counter is: 69.6235
  77. the sample is 77 the counter is: 72.8564
  78. the sample is 78 the counter is: 76.9797
  79. the sample is 79 the counter is: 76.4209
  80. the sample is 80 the counter is: 77.6325
  81. the sample is 81 the counter is: 75.9835
  82. the sample is 82 the counter is: 77.0154
  83. the sample is 83 the counter is: 77.4839
  84. the sample is 84 the counter is: 77.3489
  85. the sample is 85 the counter is: 76.4629
  86. the sample is 86 the counter is: 76.721
  87. the sample is 87 the counter is: 77.3822
  88. the sample is 88 the counter is: 78.3564
  89. the sample is 89 the counter is: 76.8349
  90. the sample is 90 the counter is: 77.8339
  91. the sample is 91 the counter is: 78.068
  92. the sample is 92 the counter is: 80.2495
  93. the sample is 93 the counter is: 81.4593
  94. the sample is 94 the counter is: 86.1396
  95. the sample is 95 the counter is: 96
  96. the sample is 96 the counter is: 73.3176
  97. the sample is 97 the counter is: 70.47
  98. the sample is 98 the counter is: 63.4537
  99. the sample is 99 the counter is: 51.3161
  100. the sample is 100 the counter is: 51.3161

实际上这个问题会有一个最佳的n值的:100/e,但是我现在用这个写的算法模拟出来之后的结果,却显得很随机,想了很久比较困惑!
至于这个1/e之一的推导是这样来的,其实当我们只对样本中最好的女生感兴趣,其他都不关注的的时候:

我们可以其实可以换一个标准就是我们取k个人只跟她们约会,不表白然后找出这k个人中最大值imax,然后相同的策略遍历后面的n-k个人:

对于某个固定的 k,如果最适合的人出现在了第 i 个位置(k < i ≤ n),要想让他有幸正好被 MM 选中,就必须得满足前 i-1 个人中的最好的人在前 k 个人里,这有 k/(i-1) 的可能。考虑所有可能的 i,我们便得到了试探前 k 个男生之后能选中最佳男生的总概率 P(k):

http://guokr.com/gkimage/ot/6r/30/ot6r30.png
用 x 来表示 k/n 的值,并且假设 n 充分大,则上述公式可以写成:

http://guokr.com/gkimage/mc/ck/q9/mcckq9.png
对 -x · ln x 求导,并令这个导数为 0,可以解出 x 的最优值,它就是欧拉研究的神秘常数的倒数—— 1/e
我们按照最大值来设计我们的模拟过程

点击(此处)折叠或打开

  1. #include<iostream>
  2. #include<ctime>
  3. #include<cstdlib>
  4. #include<vector>
  5. #include<algorithm>
  6. using namespace std;
  7. int max(vector<int> &a, int b)
  8. {
  9.     int imax = 0;
  10.     for(int i= 0; i < b; i++)
  11.     {
  12.         if(a[i] > imax)
  13.         {
  14.             imax = a[i];
  15.         }
  16.     }
  17.     return imax;
  18. }
  19. int main()
  20. {
  21.     vector<int> ivec;
  22.     vector<double> cvec;
  23.     int imax = 0;
  24.     int k = 1;
  25.     int j = 0;
  26.     for(int s = 1; s <= 100; s++)
  27.     {
  28.         ivec.push_back(s);
  29.         cvec.push_back(0.0);
  30.     }
  31.     while(k <= 10000)
  32.     {
  33.         srand(time(0));
  34.         random_shuffle(ivec.begin(), ivec.end());
  35.         for(int i = 0; i < 100; i++)
  36.         {
  37.             imax = max(ivec,i+1);
  38.             for(j = i+1; j < 100; j++)
  39.             {
  40.                 if(ivec[j] > imax)
  41.                 {
  42.                     if(ivec[j] == 100)
  43.                     {
  44.                         cvec[i]++;
  45.                     }
  46.                     break;
  47.                 }
  48.             }
  49.         }
  50.         k++;
  51.     }
  52.     for(int h = 0; h < 100; h++)
  53.     {
  54.         cout << "the sample is " << h+1 << " the counter is: " << cvec[h] << endl;
  55.     }
  56.     return 0;
  57. }

得到一下的执行结果:

点击(此处)折叠或打开

  1. the sample is 1 the counter is: 408
  2. the sample is 2 the counter is: 612
  3. the sample is 3 the counter is: 816
  4. the sample is 4 the counter is: 1123
  5. the sample is 5 the counter is: 1327
  6. the sample is 6 the counter is: 1429
  7. the sample is 7 the counter is: 1531
  8. the sample is 8 the counter is: 1735
  9. the sample is 9 the counter is: 1939
  10. the sample is 10 the counter is: 2041
  11. the sample is 11 the counter is: 2143
  12. the sample is 12 the counter is: 2143
  13. the sample is 13 the counter is: 2143
  14. the sample is 14 the counter is: 2245
  15. the sample is 15 the counter is: 2245
  16. the sample is 16 the counter is: 2245
  17. the sample is 17 the counter is: 2448
  18. the sample is 18 the counter is: 2652
  19. the sample is 19 the counter is: 2959
  20. the sample is 20 the counter is: 3061
  21. the sample is 21 the counter is: 3163
  22. the sample is 22 the counter is: 3163
  23. the sample is 23 the counter is: 3265
  24. the sample is 24 the counter is: 3265
  25. the sample is 25 the counter is: 3367
  26. the sample is 26 the counter is: 3571
  27. the sample is 27 the counter is: 3571
  28. the sample is 28 the counter is: 3571
  29. the sample is 29 the counter is: 3571
  30. the sample is 30 the counter is: 3571
  31. the sample is 31 the counter is: 3570
  32. the sample is 32 the counter is: 3672
  33. the sample is 33 the counter is: 3672
  34. the sample is 34 the counter is: 3672
  35. the sample is 35 the counter is: 3774
  36. the sample is 36 the counter is: 3672
  37. the sample is 37 the counter is: 3570
  38. the sample is 38 the counter is: 3672
  39. the sample is 39 the counter is: 3774
  40. the sample is 40 the counter is: 3876
  41. the sample is 41 the counter is: 3876
  42. the sample is 42 the counter is: 3876
  43. the sample is 43 the counter is: 3876
  44. the sample is 44 the counter is: 3877
  45. the sample is 45 the counter is: 3877
  46. the sample is 46 the counter is: 3877
  47. the sample is 47 the counter is: 3877
  48. the sample is 48 the counter is: 3877
  49. the sample is 49 the counter is: 3775
  50. the sample is 50 the counter is: 3775
  51. the sample is 51 the counter is: 3673
  52. the sample is 52 the counter is: 3571
  53. the sample is 53 the counter is: 3571
  54. the sample is 54 the counter is: 3469
  55. the sample is 55 the counter is: 3367
  56. the sample is 56 the counter is: 3264
  57. the sample is 57 the counter is: 3264
  58. the sample is 58 the counter is: 3264
  59. the sample is 59 the counter is: 3162
  60. the sample is 60 the counter is: 3162
  61. the sample is 61 the counter is: 3162
  62. the sample is 62 the counter is: 3060
  63. the sample is 63 the counter is: 2958
  64. the sample is 64 the counter is: 2856
  65. the sample is 65 the counter is: 2856
  66. the sample is 66 the counter is: 2754
  67. the sample is 67 the counter is: 2754
  68. the sample is 68 the counter is: 2652
  69. the sample is 69 the counter is: 2550
  70. the sample is 70 the counter is: 2550
  71. the sample is 71 the counter is: 2550
  72. the sample is 72 the counter is: 2448
  73. the sample is 73 the counter is: 2346
  74. the sample is 74 the counter is: 2244
  75. the sample is 75 the counter is: 2142
  76. the sample is 76 the counter is: 2040
  77. the sample is 77 the counter is: 1938
  78. the sample is 78 the counter is: 1938
  79. the sample is 79 the counter is: 1836
  80. the sample is 80 the counter is: 1734
  81. the sample is 81 the counter is: 1632
  82. the sample is 82 the counter is: 1633
  83. the sample is 83 the counter is: 1531
  84. the sample is 84 the counter is: 1429
  85. the sample is 85 the counter is: 1327
  86. the sample is 86 the counter is: 1225
  87. the sample is 87 the counter is: 1123
  88. the sample is 88 the counter is: 1021
  89. the sample is 89 the counter is: 919
  90. the sample is 90 the counter is: 816
  91. the sample is 91 the counter is: 714
  92. the sample is 92 the counter is: 714
  93. the sample is 93 the counter is: 612
  94. the sample is 94 the counter is: 510
  95. the sample is 95 the counter is: 408
  96. the sample is 96 the counter is: 306
  97. the sample is 97 the counter is: 204
  98. the sample is 98 the counter is: 102
  99. the sample is 99 the counter is: 102
  100. the sample is 100 the counter is: 0
可以看到,这次的输出是由规律的,当k = 40左右的时候选到最优秀的女生的概率是最大的,到底问题处在了什么地方了。仔细分析一下:我们采取第一种策略,取前k个人的均值,然后求解在这种策略下的找到对象的均值是均匀分布的,为什么捏?因为对于这件事情本身来看他是一个均匀的分布的事件,我们求均值的策略并没有改变其随机的特性,所以无论我们用多少个样本模拟,当然除了k=100的情况外结果应该是满足均匀分布的特性!因而可以得出这样的结论,当你只求找到平均水平靠上的女生时,无论你采取多大的k值,对于结果影响不会太大,但是除去100跟99,这两种情况,因为这样做是没有意义的!
然而我们第二种策略求解的是找到最佳女生的概率,是跟你k值的选取有密切关系的,而且满足37%的法则!即当你在1/e比例处选取样本,表现最好!当然这跟你n的取值不同会有波动!因为1/e是我们推导出来的一个极限值!



阅读(1885) | 评论(7) | 转发(0) |
给主人留下些什么吧!~~

GFree_Wind2012-11-06 12:26:57

问题倒是挺好玩的。我同意Bean_lee所说。另外,这两种策略在实际应用中,估计都不靠谱呵。

风箫夜吟2012-10-31 09:11:22

blacksapper: 这个好比摘叶子。柏拉图以前搞过的,从伦理学上来讲条件太苛刻了。我宁可不要这个条件。
只是觉得从数学的角度来讲太不符合实际了。算法的具体实现时和初.....

blacksapper2012-10-30 23:59:31

这个好比摘叶子。柏拉图以前搞过的,从伦理学上来讲条件太苛刻了。我宁可不要这个条件。
只是觉得从数学的角度来讲太不符合实际了。算法的具体实现时和初态有关。所以37那里不现实。
还是支持你的精神。

风箫夜吟2012-10-29 21:06:15

Bean_lee: 兄弟这种talk is cheap,show me the fuck code 的实干作风,我很喜欢,呵呵.....

Bean_lee2012-10-29 17:28:23

兄弟这种talk is cheap,show me the fuck code 的实干作风,我很喜欢,呵呵