01背包 页面布局

遇到一个问题,一个宽度固定的div,2行,20列(宽度容纳20个字符)。如果行内已有词语的长度+当前要放入词语的长度>20则待放入的词语会在第二行放入。

词语从数据库得到,能得到一个词语的List集合。那么,问题出现了,如果将List中的词语全部放入div中,可能超过div的大小,而选择性的放入div又要如何选择才能尽可能的利用div的大小。由于div的个数很多,人工方法尽量不考虑。若按list的顺序放入div并将当前长度存入N进行维护,则如果先放入一个长度为2的元素,第二个元素长度为19,此时是要到下一行输出还是继续需找合适的元素在第一行输出?如何保证空间利用的最大化?

不知道观众大大有没有好的方案,我目前能想到的只有用01背包。维护数组re[i][j]来存放i个待选词语放入长度为j的div的总词长。先以1行为例,两行可以重复第一行的工作。

i个词语放入j的div总词长为re[i][j],re[i][j]=max{re[i-1][j],re[i-1][j-length[i]]+length[i]}。用人话讲就是i个待选词放入j长的div的总词长=i-1个待选词放入长度为j的div的总词长和i-1个词放入长度为j-第i个词长的div时的总词长+第i个词的词长。因为re[i][j]的状态和他上一个状态有关,如果第i个词是没有放入的,他的上一个状态就是re[i-1][j],因为没有放入,所以总的div是不需要变化的。如果第i个词放入了,则上个状态显然为re[i-1][j-length[i]]。length[i]是第i个词的词长

下面是代码和注释,仅做了一行的div的情况,两行可以再跑一遍,或者去判断结果关于长度的结构是否变化再重跑部分代码

package dp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {
	public static void main(String[] args) {
		List<String> src = Arrays.asList(new String[]{"good","the","manage","test","for","new","goodIdea","dd","na","sa"});
		int clumnNum = 13;
		System.out.println(dodp(src, clumnNum));
	}
	/**re存放该行总字数 i放入个数,v列数
	 * re[i][v] = max{re[i-1][v],re[i-1][v-l[i]]+l[i]}
	 * @param src
	 * @param clumnNum
	 * @return
	 */
	public static List<String> dodp(List<String> src,int clumnNum){
		int[][] re = new int[src.size()+1][clumnNum+1];
		for(int i=0;i<src.size()+1;i++)
			re[i][0] = 0;
		for(int j=0;j<clumnNum+1;j++)
			re[0][j]=0;
		List<String> result = new ArrayList<String>();
		for(int i=1;i<src.size()+1;i++){
			for(int j=1;j<clumnNum+1;j++){
				if(j>=src.get(i-1).length()){
				int a = re[i-1][j];
				int b = re[i-1][j-src.get(i-1).length()]+src.get(i-1).length();
				if(a<b)
					re[i][j] = b;
				else
					re[i][j] = a;
				}else
					re[i][j] = re[i][j-1];
			}
		}
		int m = clumnNum;
		for(int k=src.size();k>0;k--){
			if(re[k][m]>re[k-1][m]){
				result.add(src.get(k-1));
				m -= src.get(k-1).length();
			}
		}
		return result;
	}
}

应该有更好的解决方案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值