开心
题目分析
基本思路:
对于这道题我们要遍历的是在哪一个位置上填“+”。那么我们可以定义一个数组vis[i],如果它为真表示我们在数字从左向右数第i个数字和第i+1个数字之间添加一个“+”。最后我们要判断所有的“+”是否都被用完了。
细节梳理:
因为我要遍历数字每一位上的值,所以在存数字的时候,我直接用字符数组存,这样取每一位上的值时比较方便。
Scanner sc = new Scanner(System.in);
n = sc.next();
k = sc.nextInt();
arr = n.toCharArray();
vis = new boolean[arr.length];
注意假设数字的长度为n,那么“+”不能放在位置n,因为我们要保证“+”的右边有数字,所以vis数组的结束位置应该是比n小1的地方。下面代码的end表示vis数组的结束位置。举个例子,比如1234,长度为4,我顶多在123的右边放个“+”变成123+4,即vis[2]=true,注意数组下标是从0开始的,当i遍历到3也就是vis.length - 1时,说明我该考虑的位置都考虑完了,接下来应该是求此方案下得到的数的值,所以end是结束位置。
end = vis.length - 1; //vis能插入+的有效范围 n.length - 1
接下来我们考虑在某个位置上插入“+”。如下代码,这里是stp表示当前遍历到的位置下标,ki表示当前还剩下的可以插入的“+”数量。那么对于当前位置stp来说我可以选择插入“+”,也可以不插入“+”,当i=1时表示我选择的是插入,那么这里要注意,能插入的前提是我还有“+”可以使用,所以要判断ki是否大于0。要插入的话就把vis[stp]置为true。然后进入下一个位置的dfs,如果vis[stp]为true表示我插入了,那么“+”的数量ki就要-1.dfs结束之后,我要做下一个选择了,那么我要把之前选择记录的值复原,也就是把vis[stp]变为false。
static void DFS(int stp, int ki) {
......
for (int i = 0; i < 2; ++i) { //0不插入+,1插入+
vis[stp] = i == 1 && ki > 0;
DFS(stp + 1, vis[stp] ? ki - 1 : ki);
if (vis[stp]) vis[stp] = false;
}
}
接下来,如果我把所有位置都判断完了是否添加“+”时,我要求当前情况下得到的值。
static void DFS(int stp, int ki) {
if (stp == end) {//遍历到了终点
if (ki == 0) { //当使用“+”都用完了才合法
long sum = 0;
long ans = 0;
for (int i = 0; i < arr.length; ++i) {
ans = ans * 10 + (arr[i] - '0');
if (vis[i]) {//如果出现了“+”,则加上之前的数字,然后ans重置为0.
sum += ans;
ans = 0;
}
}
sum += ans; //加上最后一个数字
if (sum < min) min = sum;//记录最小值
if (sum > max) max = sum;//记录最大值
}
return;
}
.....
}
上述过程举个例子。假设原始数字是1234,k=1,那么vis[1]=true
i=0 ans=1;i=1 ans=12 sum=sum+ans=12 ans=0;i=2 ans=3;i=3 ans=34;for循环结束,但是最后的34我没有加上,我要加上,所以有sum+=ans=sum+34=12+34=46
题目代码
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
public class Main{
static String n;
static int k, end;
static char[] arr;
static boolean[] vis;
static long min = Long.MAX_VALUE, max = 1;
static HashSet<String> set = new HashSet<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.next();
k = sc.nextInt();
arr = n.toCharArray();
vis = new boolean[arr.length];
end = vis.length - 1; //vis能插入+的有效范围 n.length - 1
sc.close();
if (n.length() > 1) {
DFS(0, k);
System.out.println(max - min);
} else {
System.out.println(0);
}
}
static void DFS(int stp, int ki) {
if (stp == end) {
if (ki == 0) { //当使用完全才合法
long sum = 0;
long ans = 0;
for (int i = 0; i < arr.length; ++i) {
ans = ans * 10 + (arr[i] - '0');
if (vis[i]) {
sum += ans;
ans = 0;
}
}
sum += ans; //加上最后一段
if (sum < min) min = sum;
if (sum > max) max = sum;
}
return;
}
for (int i = 0; i < 2; ++i) { //0不插入+,1插入+
vis[stp] = i == 1 && ki > 0;
DFS(stp + 1, vis[stp] ? ki - 1 : ki);
if (vis[stp]) vis[stp] = false;
}
}
}