2009年12月16日

          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 }


          posted @ 2009-12-25 16:13 jav7er 閱讀(170) | 評論 (0)編輯 收藏
           
          TopCoder SRM 405 Level 2 1000
          一個理想的字符串,其中每個字母第一次出現的位置N,與這個字母在字符串中出現的次數M是相等的,求給定長度的字符串中最小的一個理想字符串

          字符串長度小于100
          相當于去搜索1~100中的一組不同的數
          加起來等于長度L
          同時每個數字都要小于等于比自己小的所有數的和加一
          因為L比較小
          所以用深搜就可以了
          在這個過程中要注意深搜時候需要從大往小搜
          這樣才能滿足“最小的”結果
          搜索完之后的字符串構建的步驟因為StringBuffer用的不熟練
          反而調試了很久
           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 IdealString
           8 {
           9     int[] table = new int[26];
          10     int finalindex = 0;
          11     int L;
          12     
          13     public String construct(int length)
          14     {
          15         Arrays.fill(table, 0);
          16         L = length;
          17         if(dfs(100)){
          18             StringBuffer sb = new StringBuffer();
          19             char c = 'A';
          20             int i , j = 0;
          21             for(i = 0 ; i < L; ++ i)
          22                 sb.append(' ');
          23             for(i = 0 ; i < finalindex; ++i){
          24                 sb.setCharAt(table[i] - 1, c ++);
          25                 table[i]--;
          26             }
          27             for(i = 0 ; i < L; ++ i){
          28                 if(sb.charAt(i) != ' ')
          29                     continue;
          30                 while(table[j] == 0) j++;
          31                 sb.setCharAt(i, (char)('A' + j));
          32                 table[j]--;
          33             }
          34             return sb.toString();
          35         }
          36         return new String();
          37     }
          38     
          39     boolean dfs(int num, int index, int sum){
          40         table[index] = num;
          41         int base = num + sum;
          42         if(base == L){
          43             table[index] = num;
          44             finalindex = index + 1;
          45             return true;
          46         }
          47         if(base > L)
          48             return false;
          49         int total = 0;
          50         for(int i = 0 ; i <= index ; ++ i)
          51             total += table[i];
          52         for(int i = total + 1;  i >= num + 1-- i){            
          53             if(base + i <= L && dfs(i, index +1, base))
          54                 return true;
          55         }
          56         return false;
          57     }
          58 }


          posted @ 2009-12-25 16:00 jav7er 閱讀(145) | 評論 (0)編輯 收藏
           
          TopCoder SRM 399 Level 2 1000
          http://www.topcoder.com/stat?c=problem_statement&pm=8758&rd=12171
          給定N和一個整數集合a,用不屬于a的3個整數相乘得出離N最近的整數

          N的范圍1~1000
          從小到大3重循環就可以解
          理論上的復雜度高達1000^3
          如果確實算一次我的電腦要跑到6秒
          不過其實當乘積減去N已經超過之前的差額時就可以break了
          所以計算量其實很小
          加上break算一次只要零點零幾秒
          另外的陷阱是循環如果只是1~1000是不行的
          有可能會用到比1000還大的因子
           1import java.util.*;
           2import java.util.regex.*;
           3import java.text.*;
           4import java.math.*;
           5import java.awt.geom.*;
           6
           7public class AvoidingProduct
           8{
           9    int SIZE = 1101;
          10    
          11    public int[] getTriple(int[] a, int n)
          12    {
          13        boolean[] table = new boolean[SIZE];
          14        Arrays.fill(table, true);
          15        for(int i = 0  ; i < a.length ; ++ i)
          16            table[a[i]] = false;
          17        int x,y,z;
          18        int[] ans = new int[3];
          19        Arrays.fill(ans, Integer.MAX_VALUE);
          20        int gap = Integer.MAX_VALUE;
          21        Outer:
          22        for(x = 1 ; x < SIZE; ++ x){
          23            if(table[x] == falsecontinue;
          24            for(y = 1; y < SIZE; ++ y){
          25                if(table[y] == falsecontinue;
          26                for(z = 1 ; z < SIZE; ++ z){
          27                    if(table[z] == falsecontinue;
          28                    int total = x * y * z;
          29                    int sub = n - total;
          30                    if(Math.abs(sub) < gap){
          31                        ans[0= x; ans[1= y; ans[2= z;
          32                        gap = Math.abs(sub);
          33                    }

          34                    if(sub < 0 && Math.abs(sub) >= gap)
          35                        break ;
          36                }

          37            }

          38        }

          39        return ans;
          40    }

          41    
          42}
          posted @ 2009-12-16 21:58 jav7er 閱讀(132) | 評論 (0)編輯 收藏
           
          主站蜘蛛池模板: 江陵县| 邻水| 苍梧县| 锡林浩特市| 饶河县| 页游| 合山市| 普定县| 青龙| 永济市| 铜山县| 青浦区| 漯河市| 泸州市| 黄龙县| 广宁县| 阳新县| 安徽省| 鄂尔多斯市| 珠海市| 龙山县| 新干县| 海城市| 中卫市| 兴安县| 河东区| 定安县| 普兰店市| 四会市| 铁力市| 贵州省| 萝北县| 青岛市| 浏阳市| 视频| 鄂托克前旗| 隆昌县| 定日县| 南宫市| 定西市| 晋州市|