上图来源于强大的Q群友。。ps.侵删!
这是2020/02/28做的笔试题。当时没做出来。
现在冲~
想了两种解法:递归和dp.
递归
import java.util.Scanner;
public class Main {
//标志位
private static boolean flag = false;
int du = 0; //邪恶程度
public void check(int[] a, int n, int k) {
if (flag == true){
return;
}
if (n == 0) {
flag = true;
System.out.println(du);
}
for (int j = k - 1; j >= 0; j--) {
du++;
if (n - a[j] >= 0) {
check(a, n - a[j], k);
}
du--;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
//存放 含 4 7 的数
int[] a = new int[126];
int k = 0;
int ans = 0;
for (int i = 0; i <= n; i++) {
int ti = i;
boolean flag = false;
while (ti > 0) {
int tmp = ti % 10;
ti /= 10;
if (tmp == 4 || tmp == 7) {
if (ti <= 0) {
flag = true;
}
} else
break;
}
if (flag) {
a[k++] = i;
}
}
Main main = new Main();
//k是数组a的存放4 7 后的真实长度。
main.check(a, n, k);
if (flag == false)
System.out.println(0);
}
}
今天2020/03/01在看dp,感觉这题可以dp做就试试了
动态规划解法:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
//存放 含 4 7 的数
int[] a = new int[126];
int k = 0;
int ans = 0;
for (int i = 0; i <= n; i++) {
int ti = i;
boolean flag = false;
while (ti > 0) {
int tmp = ti % 10;
ti /= 10;
if (tmp == 4 || tmp == 7) {
if (ti <= 0) {
flag = true;
}
} else
break;
}
if (flag) {
a[k++] = i;
}
}
Main main = new Main();
//k是数组a的存放4 7 后的真实长度。
int check = main.check(a, n, k);
if (check == 1000000)
check = 0;
System.out.println(check);
}
public int check(int[] a, int n, int k) {
int[] dp = new int[n + 1];
/*
dp[i] = x; 意义:数字i的邪恶程度是x
因为要找的是一个数字的邪恶程度的最小值。
先初始化dp[i] = 1000000,方便筛选。 dp[i] = Math.min(dp[i], 1 + dp[i - a[j]]);
*/
for (int i = 0; i < n + 1; i++)
dp[i] = 1000000;
// 数组a存放的是 <= n 中含4 7 47这样的数组,邪恶程度是 1.
for (int i = 0; i < k; i++)
dp[a[i]] = 1;
//k是数组a的存放4 7 后的真实长度。
/*
比如 n = 40, 数组a={4,7}.
dp[43] = min (dp[43], 1+dp[43-7]) , dp[43] = min (dp[43], 1+dp[43-4])
dp[43-7] = dp[36]
dp[36-7] = dp[29]
dp[29-7] = dp[22]
dp[22-7] = dp[15]
dp[15-7] = dp[8]
dp[8] = min (dp[8], 1+dp[8-7]) = min(dp[8],1+dp[1]) = min(1000000,1000001) = 1000000
然后j--使用a[0]
dp[8] = min (dp[8], 1+dp[8-4]) = dp[4] = 1;
*/
for (int i = 5; i < dp.length; i++) {
//下面两种for循环均可。
//for (int j = 0; j < k; j++) {
for (int j = k - 1; j >= 0; j--) {
//dp[i - a[j]] 确保不会越界。
if (i - a[j] < 0)
continue;
dp[i] = Math.min(dp[i], 1 + dp[i - a[j]]);
}
}
for (int i = 0; i < dp.length; i++) {
System.out.printf(" i==" + i + " " + dp[i] +"\n");
}
return dp[n];
}
}