n个数字里面选k个,和不超过sum,有几种选择方法

Q:原问题是请人吃饭,一共有多少种点菜的方法,其实本质是n个数字里面选k个,和不超过sum,有几种选择方法。
A:经典01背包问题中并没有限定取多少个,但是该题限定为k个,参考《编程之美》2.18数组分割的思路,对背包进行一些小的改进。
代码如下

//DFS()是暴力的方法,partition是DP的方法
//main()方法里是一个对数器
import java.util.*;
public class 请吃饭
{
    public static int mod=1000_0000_7;
    public static int ways;
    public static void DFS(int n,int k,int money,int[] arr)
    {
        if (n>=0&&k==0&&money>=0)
        {
            ways++;
            ways%=mod;
            return;
        }
        else if (n<=0)
        {
            return;
        }
        //剪枝
        if (k>n)
        {
            return;
        }
        //第n道菜不选
        DFS(n-1,k,money,arr);
        //第n道菜选掉
        DFS(n-1,k-1,money-arr[n-1],arr);
    }
    public static int partition(int n,int k,int money,int[] arr)
    {
        int[][] dp=new int[k+1][money+1];
        dp[0][0]=1;
        //temp表示可选范围从1个到temp个元素
        for (int temp=1;tempk?k:temp);i>=1 ;i-- )
            {
                for (int j=0;j=arr[temp-1]&&(dp[i-1][j-arr[temp-1]]>0))
                    {
                        dp[i][j]+=dp[i-1][j-arr[temp-1]];
                        dp[i][j]%=mod;
                    }
                }
            }
        }
        int sum=0;
        //这里j要能等于0,因为当k为0的时候,应该返回1
        for (int j=money;j>=0 ;j-- )
        {
            sum+=dp[k][j];
            sum%=mod;
        }
        /*
        for (int i=0;i"+res);
            if (res!=ways)
            {
                System.out.println("fuck man ");
            }
        }
    }
}

你可能感兴趣的:(n个数字里面选k个,和不超过sum,有几种选择方法)