婚姻稳定性问题的模拟

简介

百科http://baike.baidu.com/subview/11804317/12175605.htm

婚姻的稳定性问题就是研究 N 对男女在允许自由组合的情况下最终稳定的结果。假设这 N 对男女中,一开始都是单身,所有单身男生开始追求自己心目中最优秀的女生,而女生则会选择其眼中最优秀的追求者,并拒绝其他男生。其他男生一旦被拒绝就不再追求该女生,而是转向去追求自己心目中次优的女生。当一个处于恋爱关系中的女生遇到一个更好的男生的追求时,她就会甩掉当前的男朋友,选择更好的男生作为新男朋友。以此类推,直到所有人都结成情侣为止。
本实验在此基础上进行改进,只有当新追求者比旧追求者得分高出一定值的时候才选择后者。

PHP实现http://simplebymoming.applinzi.com/marriage.html(5对以内能在有限时间内跑出结果,3对一般都能很快得到结果)

事实证明,用PHP实现这个真的是很愚蠢的做法。当对数增加时,会使得复杂度变得很大,而得不到最终结果的时候网页无法完成加载,所以最后的结果就是跑死了。。。仅仅是为了好玩。

新增MATLAB代码:https://github.com/Momingcoder/Mathematical-Modeling/tree/master/Stable%20Marriage


Modeling

  • 需要用户输入的为couple和tolerate。其中couple为必须输入项,tolerate为可选输入,若不输入则默认为0。
  • 首先需要对用户提交的表单数据进行处理,过滤其中的空格以及不安全项:
function test_input($data) {//处理表单数据
        $data = trim($data);
        $data = stripslashes($data);
        $data = htmlspecialchars($data);
        return $data;
}
  • 为了实现该功能,需要设置一下矩阵及向量:
  • 男生对女生的评分矩阵:$MaleScore(0~100分,随机数)
  • 女生对男生的评分矩阵:$FemaleScore(0~100分,随机数)
  • 单身男生列表:$MaleSingle(1代表单身,0代表非单身)
  • 女生男朋友列表:$FemaleCouple(对应数值为男生的编号)
  • 女生被男生追求的矩阵:$FemaleList(1代表被该男生追求)
  • 男生被女生拒绝的矩阵:$MaleList(1代表被该女生拒绝)
//矩阵的初始化
$MaleScore = array();//男生对女生的评分
for($i = 0; $i < $couple; $i++) {
    $tmpscore = array();
    for($j = 0; $j < $couple; $j++) {
        array_push($tmpscore, rand(0, 100));
    }
    arsort($tmpscore);
    array_push($MaleScore, $tmpscore);
}

//列表的初始化
$MaleSingle = array();//单身男生列表
for($i = 0; $i < $couple; $i++) {
    array_push($MaleSingle, 1);
}
  • 对该过程的模拟,如果还有单身男生,则说明还有人没有结成对,则需要继续循环:
while(max($MaleSingle) != 0) {}
  • 在循环体内,首先要每个单身的男生对自己最喜欢且没被拒绝过的女生表白,即在FemaleList中对应项置为1,其中对最喜欢女生的序号的获取函数为:
function getManLover($score, $list) {//获取下一个表白的序号
    $tmp = 0;
    $pos = 0;
    for($i = 0; $i < $GLOBALS['couple']; $i++) {
        if($tmp < $score[$i] && $list[$i] == 0) {
            $tmp = $score[$i];
            $pos = $i;
        }
    }
    return $pos;
}
  • 之后,对每个女生寻找一个追求者中得分最高的,获取该序号的函数为:
function getWomanLover($score, $list, $single) {//获取最佳追求者序号
    $tmp = 0;
    $pos = -1;
    for($i = 0; $i < $GLOBALS['couple']; $i++) {
        if($tmp < $score[$i] && $list[$i] == 1 && $single[$i] == 1) {
            $tmp = $score[$i];
            $pos = $i;
        }
    }
    return $pos;
}
  • 如果该函数返回-1,则表示没人向该女生表白;否则,判断该女生是否已有对象,若没有则将该男生设置为其男朋友,并将该男生设置为非单身状态:
if($FemaleCouple[$i] == -1) {//还没男朋友的
    $FemaleCouple[$i] = $pos;
    $MaleSingle[$pos] = 0;
}
  • 若该女生已有对象,则比较原对象与新对象的分数,如果新对象比旧对象得分搞过tolerate,则将原对象设置为单身状态,将新对象设置为非单身状态,并设置改男生已被该女生拒绝:
elseif($FemaleScore[$i][$pos] - $FemaleScore[$i][$FemaleCouple[$i]] > $tolerate) {
    $MaleList[$FemaleCouple[$i]][$i] = 1;
    $MaleSingle[$pos] = 0;
    $MaleSingle[$FemaleCouple[$i]] = 1;
    $FemaleCouple[$i] = $pos;                                   
}
  • 之后,将该女生没接受的男生设置为被改女生拒绝:
function refuseExcept($pos, $list, $target) {//拒绝其他人
    global $MaleList;
    for($i = 0; $i < $GLOBALS['couple']; $i++) {
        if($i != $pos && $list[$i] == 1) {
            $MaleList[$i][$target] = 1;
        }
    }
}
  • 不断循环以上步骤,直到没有单身男生为止。
  • 最后,打印矩阵MaleScore和FemaleScore,并输出配对情况:
echo "couple: $couple <br> tolerate: $tolerate <br>" ;
echo "Girls' score in boys' eyes( i 行 j 列的数值表示在第 i 个男生眼中第 j 个女生的得分)<br>";
for($i = 0; $i < $couple; $i++) {
    for($j = 0; $j < $couple; $j++) {
        echo $MaleScore[$i][$j], "\t";
    }
    echo "<br>";
}
echo "Boys' score in girls' eyes( i 行 j 列的数值表示在第 i 个女生眼中第 j 个男生的得分)<br>";
for($i = 0; $i < $couple; $i++) {
    for($j = 0; $j < $couple; $j++) {
        echo $FemaleScore[$i][$j], "\t";
    }
    echo "<br>";
}
echo "<br>---------------result----------------<br>";
for($i = 0; $i < $couple; $i++) {
    echo "Couple".($i+1).": Girl's score in boy's eyes: ".$MaleScore[$FemaleCouple[$i]][$i]."------Boy's score in girl's eyes: ".$FemaleScore[$i][$FemaleCouple[$i]]."<br>";
}

结果

smp1
smp2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值