动态规划解决整数划分问题

sxiaobei 2015-07-07 12:54:25
前几天去华为做机试,遇到一个整数划分的问题,题目是:现有1,2,5,10,20,50,100 元这几种钱币,问给定n元能有多少种分配方式。例如n=4时,有1+1+1+1 ,1+2+1 , 2+2 三种划分。我解决这道题是从网上看的方法,用的递归,但是悲剧的是测试用例运行超时,结果题没做出来,我直觉上觉得用动态划分可以解决,所以就研究了动态划分的解法。

首先,先找出划分,每种组合以最大面值等于多少就形成一个划分:
例如:现在这道题,有 1 , 2 , 5 ,10 ,20 ,50 , 100这7种划分,每种划分的定义是,m划分代表,在这些钱币中,最大的钱币为m。

找出划分后再找出递推公式,这个递推公式在网上找,一大堆,但是针对这个问题的递推公式为:
n代表钱数,m代表划分数
1. 当n==1或者是m==1时,q(n , m)=1;
2. 当n==m时,q(n , m)=q(n,m-1)
3. 当n<m时,q (n , m)=q(n,n)
4. 当n>m时,q(n , m)= q(n ,m-1)+q(n-m,m)i

然后找出初始条件,初始条件就是当n==0,时,所有划分都等于0,所以再二维数组的第一行都为0,二维数组,行代表你的钱数,列数代表的划分数,这些划分的值在一个一维数组中存着,所以二维数组的列代表,上面一维数组的索引。还有就是当1划分的时候,所有值都等于1(二维数组的值就是拆分的个数)。

然后就按照上面的递推公式来填充二维数组,最后返回你钱数的最大划分就是最终结果,我是根据01背包问题研究的这道题,如有不懂请参见经典的01背包问题,如写的不好,请大家多批评,下面是我的代码:直接可以运行出结果

package com.test;

public class Main {

static int[] qian=new int[]{1,2,5,10,20,50,100};

public static int get(int money){
int[][] test=new int[money+1][7];
for(int i=0;i<test.length;i++){
if(i==0){
for(int j=0;j<qian.length;j++){
test[i][j]=0;
}
}else{
for(int j=0;j<qian.length;j++){
if(qian[j]==1){
test[i][j]=1;
}else{
if(i<qian[j]){
test[i][j]=test[i][j-1];

}else if(i==qian[j]){
test[i][j]=test[i][j-1]+1;
}else if(i>qian[j]){
test[i][j]=test[i-qian[j]][j]+test[i][j-1];
}
}
}
}
}
for(int i=0;i<=money;i++){
for(int j=0;j<qian.length;j++){
System.out.print(test[i][j]+" ");
}
System.out.println();
}
return test[money][qian.length-1];
}
public static void main(String[] args) {
System.out.println(get(250));

}

}
...全文
541 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
Inhibitory 2015-07-07
  • 打赏
  • 举报
回复
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class Calculator {
    private static final int[] UNITS = {100, 50, 20, 10, 5, 1};
    private List<String> components = new LinkedList<String>();
    private int target;
    private Set<String> results = new TreeSet<String>();

    public Calculator(int target) {
        this.target = target;
    }

    public void calculate() {
        doCalculate(target, 0, 0);
    }

    public Set<String> getResults() {
        return results;
    }

    private void doCalculate(int target, int currentSum, int index) {
        if (target == currentSum) {
            results.add(components.toString());
            return;
        }

        for (int s = index; s < UNITS.length; ++s) {
            for (int i = 0; i <= (target - currentSum) / UNITS[s]; ++i) {
                if (currentSum + UNITS[s] * i <= target) {
                    if (i != 0) {
                        components.add(UNITS[s] + " * " + i);
                    }

                    doCalculate(target, currentSum + UNITS[s] * i, s + 1);

                    if (i != 0) {
                        components.remove(components.size() - 1);
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Calculator calculator = new Calculator(36);
        calculator.calculate();
        calculator.getResults().stream().forEach(System.out::println);
    }
}

50,686

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧