动态规划算法,求指导

hao_neverstop 2016-07-11 10:41:46
实际问题描述:

有一个数据类型为整数的集合(可以声明一个整型的数组),这个数组的元素个数不定但基本会在20-80之间,
元素的取值范围1-30之间,接下来问题来了?

要求:
1、从这个数组集合里取任意个元素进行相加求和,要求求得的和“无限接近或等于30”,也就是说越接近30越好,因为实际情况肯定会有一些元素是1,2,3这些比较小的数,和一些27,28,29,这样比较大的数,所以基本上不会出现只取一个值得情况,也就是说最少会取两个。

2、求和时所取得元素个数有个限制不能超过 m ,m 是个变量可以手动设置,也就是说可以手动控制求和元素的个数。

3、再取元素的过程中,原则是取得元素个数越少越好,最后有些实在没办法了也可能避免不了出现 1+ 1 + 1 + 1 = 4的情况,这个是允许的, 但最好是凑成 28 + 1 或是 22 + 7 或是 27 + 1 这种相加元素少,但很接近三十的

4、所有的元素只可以取一次,参与一次运算,不可使用多次。

5、最后需要返回的结果是这些参与求和的元素的组合,组成的List,因为相同值的元素会有许多,所以为了在结果中区分是不是一个元素只用了一次 可以将最开始的数组声明为List<Map(<Stirng,Object>> 这样的形式 这样就可以用唯一标记值来标识后面的元素值了,类似于数据库中的id,建议最好做成List<Map(<Stirng,Object>>这种形式,输出的话会是如下样子:

{{"1",29},{"5",1}}
{{"2",28},{"3",2}}
{{"6",1},{"7",1},{"8",1},{"9",1}}
引号里的事Map的key值,逗号后面的数是真正的元素值。

说明:方案和算法也许有很多,可以先实现然后再逐渐寻找最优。

实际的应用场景可以理解为,一大堆不同种类的货物,要往能装下固定数量货物的箱子中放,要求就是每个箱子中的货物种类要尽量少,如果箱子凑不满要尽量凑满,尽量接近最大数,实在没法了可以存在好几个不同的品种的货物都很少的情况,但要尽量避免,如果按照上面的输出方式的话也可以
表明每个箱子中的货物种类
...全文
152 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
rickylin86 2016-07-11
  • 打赏
  • 举报
回复

import java.util.Random;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;

public class Test{
	public static void main(String[] args){
		ArrayList<Integer> values = Tool.getIntegerArray();
		int m = 3;//用于设置相加元素的个数
		int max = 30;//用于设置相加不超过的数字
		ArrayList<ArrayList<Integer>> results = Tool.process(values,m,max);
		for(int i = 0 ; i < results.size() ; i ++){
			System.out.print(i + 1 + ":");
			ArrayList<Integer> result = results.get(i);
			for(int j = 0 ; j < result.size() ; j ++ ){
				System.out.print(result.get(j) + ((j != result.size() - 1) ? "+" : ""));
			}
			System.out.println();
		}
	}
}

class Tool{
	public static ArrayList<Integer> getIntegerArray(){
		
		Random random = new Random();
		
		int size = 20 + random.nextInt(60);
		
		ArrayList<Integer> results = new ArrayList<>();

		for(int i = 0 ; i < size ; i ++){
			results.add(1 + random.nextInt(29));
		}

		Collections.sort(results);//这里排序为了后续的操作方便
		
		ArrayList<Integer> temps = new ArrayList<>();

		for(int i = size - 1 ; i >= 0 ; i --){
			temps.add(results.get(i));
		}

		//采用倒序返回,因为实现目标是为了不大于某个数值m个数的相加.

		results = temps;
		

		return results;
	}

	public static ArrayList<ArrayList<Integer>> process(ArrayList<Integer> values , int count , int total){

		assert total >= values.get(0);
		
		ArrayList<ArrayList<Integer>> results = new ArrayList<>();

		int currentTotal = 0;
		int value = 0;
		ArrayList<Integer> result = null;
		int time = 0;
		
		while(values.size() > 0){
			result = new ArrayList<>();
			if(values.size() == 1){
				result.add(values.remove(0));
				results.add(result);
				break;
			}
			currentTotal = values.remove(0);
			result.add(currentTotal);
			time = 0;
			for(int index = 0 ; index < values.size() ; index ++){
				if(currentTotal + values.get(index) > total){
					continue;
				}
				value = values.remove(index);
				currentTotal += value;
				result.add(value);
				time ++;
				if(time > count){
					break;
				}
			}

			results.add(result);
		}

		return results;
	}
}

50,526

社区成员

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

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