遇到一个问题,一个宽度固定的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;
}
}
应该有更好的解决方案