题目:
现在你要研发一种新型的碎纸机,待粉碎的纸上面有一串数字,要求把纸粉碎成的几片上的数字的和尽量接近而不能超过给定的数字target number。比如:一片纸上的数字为12346,target number为50,那么就可以把纸粉碎为1、2、34、6,其加和为43,是所有粉碎方法中最接近50而不超过50的最优解。
分析:这种是一个基本的DFS题目,用来入门是相当不错的.
题目换句话来理解就是有一串数字中间用+号来连接,使其结果小于或等于指定值的最优解.
EG:
总量50 对应字串12346
那么可以分为以下几种情况
50 1+2+3+4+6=16
50 12+3+4+6=25
50 123+4+6=133
50 1+23+4+6=34
等等…
那么我们就可以挨个试,也就是暴力搜索的方法,当然也要剪枝来提高效率.先看看基本的递归图
“”表示剩余字串,也就是下一步要递归的字串
跟着图的思路,那么代码就很容易写出来了,这里只写了一个样例程序,具体输入输出格式可以自己改写
public class Main {
static int sumTotal = 50;//规定最大值
static String num = "12346";//规定字串
static int max = 0;//得到最大值结果
static boolean isCheck = true;//当前最大值结果是否唯一
static StringBuilder builder = new StringBuilder();//当前最大值结果对应的方式
public static void main(String[] args) {
DFS(num, 0);
}
private static void DFS(String num,int curSum){
//递归结束条件
if (num == null || "".equals(num)) {
if (curSum == max) {
isCheck = false;
System.err.println(builder.toString()+"---max = "+max+"---check:"+isCheck);
return ;
}else if (curSum > max) {
max = curSum;
isCheck = true;
//记录结果,打印
System.err.println(builder.toString()+"---max = "+max+"---check:"+isCheck);
builder.delete(0, builder.length());
return ;
}
}
//这里是循环的主体
for (int i = 0; i < num.length(); i++) {
int startNum = Integer.parseInt(num.substring(0,i+1));
//剪枝,当总和大于total就没必要往后递归了
if ((curSum + startNum)>sumTotal) {
return;
}
//暂存结果,回溯的时候赋值给builder
StringBuilder temp = new StringBuilder(builder);
builder.append(startNum).append(" ");
//下一步递归
DFS(num.substring(i+1),curSum+startNum);
builder = temp;
}
}
}
结果很容易得出
时间: 2024-10-06 21:26:14