农民分羊问题

1. 农民分羊问题
问题描述: 农民有n个儿子,邻居有m头羊,农民怎么分羊?
(题设:儿子分配的多少与大小正比,允许几个儿子分到一样多的羊)
  1. 题分析和模型建立:

    当 m = 1 时 , 解 决 原 题 其 实 是 求 解 1 x 1 + 1 x 2 + ⋯ + 1 x n + 1 = 1 的 不 定 方 程 的 所 有 可 能 解 这 是 个 不 定 方 程 的 的 问 题 , 利 用 递 归 便 可 以 解 决 当 m ! = 1 时 , 题 为 1 x 1 + 1 x 2 + ⋯ + m x n + 1 = 1 怎 么 把 这 里 化 为 第 一 种 的 形 式 呢 , 这 里 提 出 两 个 方 法 当m=1时,解决原题其实是求解\frac{1}{x_1}+\frac{1}{x_2}+\cdots+\frac{1}{x_{n+1}}=1的不定方程的所有可能解\\这是个不定方程的的问题,利用递归便可以解决\\当m!=1时,题为\frac{1}{x_1}+\frac{1}{x_2}+\cdots+\frac{m}{x_{n+1}}=1\\怎么把这里化为第一种的形式呢,这里提出两个方法 m=1x11+x21++xn+11=1便m!=1x11+x21++xn+1m=1

    1. 将最后一项拆成m项

      优点:较容易想到,直接在1题的代码上加判定就可

      缺点:计算量较大(增加了m个迭代的维度,且判定会增加时间复杂度)

    2. 将原式变形

      将 原 式 化 为 1 m ∗ x 1 + 1 m ∗ x 2 + ⋯ + 1 x n + 1 = 1 m 这 样 把 m ∗ x i 看 为 整 体 y i , 寻 找 m ∣ y i 的 即 可 计 算 量 并 不 明 显 增 加 , 且 依 然 化 为 了 跟 一 题 基 本 一 样 的 迭 代 将原式化为\frac{1}{m*x_1}+\frac{1}{m*x_2}+\cdots+\frac{1}{x_{n+1}}=\frac{1}{m}\\这样把m*x_i看为整体y_i,寻找m|yi的即可\\计算量并不明显增加,且依然化为了跟一题基本一样的迭代 mx11+mx21++xn+11=m1mxiyi,myi

    3. 模型建立:

      综上所述,模型即为求解 1 m ∗ x 1 + 1 m ∗ x 2 + ⋯ + 1 x n + 1 = 1 m \frac{1}{m*x_1}+\frac{1}{m*x_2}+\cdots+\frac{1}{x_{n+1}}=\frac{1}{m} mx11+mx21++xn+11=m1的满足条件的xi组数

      接下来就是利用代码迭代实现。

  2. 流程图分析(解不定方程)

    Created with Raphaël 2.2.0 输入n,m 确定一下值: 现在还剩的比例x; 已分配的儿子个数a; 取下一个儿子分配比例: 必须<=现在的比例x,并>=x除以剩余儿子个数a x==0 && a==n? 输出分配方式 x==0 | x=1;a=0; yes no yes no
  3. 代码实现 (Java)

    package homework;
    
    import java.util.Scanner;
    
    public class DivideSheep {
    	static int[][] re = new int[10000][10];
        \\如果n的个数增加,可能会增加10000(结果的个数)
    	static int[] st = new int[10];
    	static int count = 0;
    	static int num = 4,ne = 1;//儿子的个数和邻居的样数。默认为1
    	
    	public static void divide(Fraction x, int a,int before) {
    		// Fraction是现在剩余的分数,a是已分配的个数,before是上一个分数
    		// 其实before可以省略,因为等于re[count][a],但是为了简便;
    		int tmp,tmp1;
    		
    		if(x.numerator == 0 && a == num) {
    			for(int i=0;i<num;i++)
    				re[count][i] = st[i];
    			count++;  
    		}
    		if( a == num || x.numerator == 0) return;
    		
    		
    		tmp = x.denominator / x.numerator ;
    		tmp1 = x.denominator % x.numerator == 0 ? tmp : tmp+1;
    		tmp1 = tmp1 > before ? tmp1 : before;
    		
    		for(int i=tmp1 ; i <= tmp*(num-a); i++) {
    			if(i%ne != 0) continue;
    			st[a] = i; 
    			divide(x.sub(new Fraction(1,i)),a+1,i);
    		}
    		
    		return ;
    	}
    	
    	public static void main(String args[]) {
    		System.out.print("请输入儿子个数和邻居的羊数:\n");
    		Scanner in = new Scanner(System.in);
    		num = in.nextInt()+1;ne = in.nextInt();
    		divide(new Fraction(1,1*ne),0,2);
    		System.out.print("分配方法为:\n");
    		for(int i=0;i<count;i++) {
    			for(int j=0;j<num-1;j++)
    				System.out.print("第"+(j+1)+"个儿子分1/"+re[i][j]/ne+" ");
    			System.out.print("农民有"+(re[i][num-1]-ne)+"条羊");
    			System.out.print("\n");
    		}
    		in.close();
    	}
    }
    
  4. 样例截图

    1. n = 4, m = 1; n=3,m=2;

在这里插入图片描述

  1. 模型分析

    ​ 在经过实验后,可以发现当n=5时,结果已经达到了千位的数量级,可想而知,儿子的个数越多,计算量越大,因此前面第一种算法的去电也就更明显,因为当n很大的时候,没加一个维数就会增加巨大的计算量,这也是我选择第二种算法的原因。

型分析

​ 在经过实验后,可以发现当n=5时,结果已经达到了千位的数量级,可想而知,儿子的个数越多,计算量越大,因此前面第一种算法的去电也就更明显,因为当n很大的时候,没加一个维数就会增加巨大的计算量,这也是我选择第二种算法的原因。

​ 而且,在计算机中,递归是一种非常耗时的数据结构,但普通不定方程的解法 就是与这种递归十分类似,所以可以知道,不定方程的普通解是非常耗时的,所以如果加上一些特殊条件会更好解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值