有些网站只讲了代码递归原理,但不能弄明白怎么分的财产,我找了个图,应该够简单易懂了吧
背景
争执大衣
• 《塔木德·损害部·中门卷》有则故事:甲、乙两人共同抓着一件大衣来找法官,
若甲、乙都发誓自己拥有全部所有权, 法官会判定甲、乙分别得到这件大衣的二分之一.
若甲发誓自己拥有全部所有权, 乙发誓拥有二分之一,则法官会判定甲拥有大衣四分之三,乙拥有四分之一。
• 法官判甲拥有四分之三,乙拥有四分之一。
三妻争产
• 当有100个金币,各33.3
• 当有200个金币,大75,二75,三50
• 当有300个金币,大150,二100,三50
• 如何得出的?
解决问题的三原则
*1. 仅分割有争议财产,无争议财产不予分割.
- 宣称拥有更多财产权利一方最终所得不少于宣称拥有较少权利
一方. - 财产争议者超过两人时,将所有争议者按照其诉求金额排序,
最小者自成一组, 剩下所有争议者另成一组, 争议财产在两组
间公平分配.*
老师讲解的思路
我的思路
沙漏图出处
如图所示,我的思路:
- 当财产小于债权之和一半时,从最低层级债权开始逐层满足;
- 当财产 大于等于 债权一半时,从债权最高者到最低者逐层分配;
- 当财产大于债权之和时(图片没给出这种情况),所有人均分额外财产。
python代码(思路有了,代码很简单)
- 当财产不足所有人债权之和一半时
if money<sum_rights/2:
l3=[]
for i in range(n):
if money>l2[i]*(n-i):
for j in range(i,n):
l3[j]=l2[i]
money-=( l2[i]*(n-i) )
else:
for j in range(i,n):
l3[j]+=money/(n-i)
print('分配列表',l3)
break
- 当超过一半时
elif (sum_rights/2)<=money<sum_rights:
l3=l2
money-=(sum_rights/2)
for i in range(1,n):
if money>(l2[n-i] - l2[n-i-1])*i:
for j in range(n-i,n):
l3[j]+=(l2[n-i] - l2[n-i-1])
money-=(l2[n-i] - l2[n-i-1])*i
else:
for j in range(n-i,n):
l3[j]+=money/i
print('分配列表',l3)
money=0
break
if money!=0:#前面的循环是1~n-1层,最后一层单独在此分配
l3=[i+money/n for i in l3]
print('分配列表',l3)
- 当超过债权之和时
else:
each_add=(money-sum_rights)/n
l3=[i+each_add for i in l]
print('分配列表',l3)
完整代码,循环实现
#输入:财产、人数、债权
money=float(input('财产(float):'))
n=int(input('人数:'))
l=[]
for i in range(1,n+1):
l.append(int(input("债权%d (int):"%i)))
l.sort()#债权从小到大排序
print('债权列表',l)
sum_rights=sum(l)
l2=[i/2 for i in l]#债权一半
#当财产小于债权之和一半时
if money<sum_rights/2:
print()
l3=[]
for i in range(n):
if money>l2[i]*(n-i):
for j in range(i,n):
l3[j]=l2[i]
money-=( l2[i]*(n-i) )
else:
for j in range(i,n):
l3[j]+=money/(n-i)
print('分配列表',l3)
break
#当财产 大于等于 债权一半时
elif (sum_rights/2)<=money<sum_rights:
l3=l2
money-=(sum_rights/2)
for i in range(1,n):
if money>(l2[n-i] - l2[n-i-1])*i:
for j in range(n-i,n):
l3[j]+=(l2[n-i] - l2[n-i-1])
money-=(l2[n-i] - l2[n-i-1])*i
else:
for j in range(n-i,n):
l3[j]+=money/i
print('分配列表',l3)
money=0
break
if money!=0:#前面的循环是1~n-1层,最后一层单独在此分配
l3=[i+money/n for i in l3]
print('分配列表',l3)
#当财产大于债权之和时
else:
each_add=(money-sum_rights)/n
l3=[i+each_add for i in l]
print('分配列表',l3)
运行结果
以折线图形式展示结果
完整代码,粘贴复制即可
import matplotlib.pyplot as plt
def tamude(money,n,l):
#print('财产',money)
l.sort()#债权从小到大排序
#print('债权列表',l)
sum_rights=sum(l)
l2=[i/2 for i in l]#债权一半
#当财产小于债权之和一半时
if money<sum_rights/2:
l3=[0 for i in range(n)]
for i in range(n):
if money>l2[i]*(n-i):
for j in range(i,n):
l3[j]=l2[i]
money-=( l2[i]*(n-i) )
else:
for j in range(i,n):
l3[j]+=money/(n-i)
#print('分配列表',l3)
return l3
break
#当财产 大于等于 债权一半时
elif (sum_rights/2)<=money<sum_rights:
l3=l2
money-=(sum_rights/2)
for i in range(1,n):
if money>(l2[n-i] - l2[n-i-1])*i:
for j in range(n-i,n):
l3[j]+=(l2[n-i] - l2[n-i-1])
money-=(l2[n-i] - l2[n-i-1])*i
else:
for j in range(n-i,n):
l3[j]+=money/i
#print('分配列表',l3)
money=0
return l3
break
if money!=0:#前面的循环是1~n-1层,最后一层单独在此分配
l3=[i+money/n for i in l3]
#print('分配列表',l3)
return l3
#当财产大于债权之和时
else:
each_add=(money-sum_rights)/n
l3=[i+each_add for i in l]
#print('分配列表',l3)
return l3
if __name__ == '__main__':
#a计算次数/精细度 l债权列表
a=10
l=[100,200,300]
n=len(l)
#
y=[money*100 for money in range(a)]
x=[]
for money in range(a):
x.append(tamude(money*100, n, l))
x=list(map(list, zip(*x)))#二维数组/矩阵转置
# 这两行代码解决 plt 中文显示的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 标题 坐标轴(文字大小)
plt.title("分配方案", fontsize=20)
plt.xlabel("财产", fontsize=14)
plt.ylabel("分配额", fontsize=14)
#设置水平虚线,方便观察
plt.grid(linestyle='--')#supported values are '-', '--', '-.', ':', 'None', ' ', '', 'solid', 'dashed', 'dashdot', 'dotted'
#n个人画n条线
for i in range(n):#n个人 n条线 a个点(点代表不同财产时三人分配方案)
plt.plot(y, x[i],label='债权'+str(l[i]))
#左上角图例
plt.legend()
#秀
plt.show()
运行结果
跳至简略版