TopCoder SRM 403 Level2 1000
4和7是幸运数字,如果一个数只包含4和7,那么这个数字也是一个幸运数字
给定一个1-1,000,000的数字,求这个数字是否可以仅由幸运数字相加得出,返回所有的幸运数字加数,如果有多组解,返回加数最少的一组
以前没有遇到过这样的DP题目
这题加深了我对于“每个子问题的答案都是最佳答案”的理解
首先是额外的计算
将范围以内的幸运数字打表
然后从输入数字N开始递减DP计算
N的步数为0
如果最后0的步数为正数
说明有解
再从0开始递增寻找解的路径
不过这个方法最后也没有通过tc的系统测试
数字一大就超时了
后面又时间再研究一下
看看有没有办法在改进
1 import java.util.*;
2 import java.util.regex.*;
3 import java.text.*;
4 import java.math.*;
5 import java.awt.geom.*;
6
7 public class TheSumOfLuckyNumbers
8 {
9
10 public int[] sum(int n)
11 {
12 ArrayList<Integer> table = calTable();
13 int[] dp = new int[n+1];
14 Arrays.fill(dp, Integer.MAX_VALUE-10);
15 dp[n] = 0;
16 int i , j;
17 for(i = n; i > 0 ; -- i){
18 for(int lucky:table){
19 if(i - lucky >=0 && dp[i] + 1 < dp[i - lucky])
20 dp[i - lucky] = dp[i] + 1;
21 }
22 }
23 if(dp[0] == Integer.MAX_VALUE)
24 return new int[0];
25 ArrayList<Integer> ans = new ArrayList<Integer>();
26 int total = dp[0]-1;
27 for(i = 0 ; i <= n; ++ i){
28 for(int lucky:table){
29 if(i + lucky <= n && dp[i + lucky] == total){
30 ans.add(lucky);
31 i += lucky-1;
32 total--;
33 break;
34 }
35 }
36 }
37 int[] ret = new int[ans.size()];
38 for(i = 0 ; i < ans.size(); ++ i)
39 ret[i] = ans.get(i);
40 return ret;
41 }
42
43
44
45 public ArrayList<Integer> calTable(){
46 ArrayList<Integer> table = new ArrayList<Integer>();
47 table.add(4);
48 table.add(7);
49 int i = 1;
50 while(i < 7){
51 ArrayList<Integer> temp = new ArrayList<Integer>();
52 for(int j = 0 ; j < table.size(); ++ j){
53 int newItem = table.get(j) * 10;
54
55 temp.add(newItem+4);
56 temp.add(newItem+7);
57 }
58 i++;
59 table.addAll(temp);
60 }
61 return table;
62 }
63 }