2009年12月15日

          TopCoder SRM 403 Level2 1000
          4和7是幸運(yùn)數(shù)字,如果一個(gè)數(shù)只包含4和7,那么這個(gè)數(shù)字也是一個(gè)幸運(yùn)數(shù)字
          給定一個(gè)1-1,000,000的數(shù)字,求這個(gè)數(shù)字是否可以僅由幸運(yùn)數(shù)字相加得出,返回所有的幸運(yùn)數(shù)字加數(shù),如果有多組解,返回加數(shù)最少的一組

          以前沒(méi)有遇到過(guò)這樣的DP題目
          這題加深了我對(duì)于“每個(gè)子問(wèn)題的答案都是最佳答案”的理解
          首先是額外的計(jì)算
          將范圍以內(nèi)的幸運(yùn)數(shù)字打表
          然后從輸入數(shù)字N開(kāi)始遞減DP計(jì)算
          N的步數(shù)為0
          如果最后0的步數(shù)為正數(shù)
          說(shuō)明有解
          再?gòu)?開(kāi)始遞增尋找解的路徑

          不過(guò)這個(gè)方法最后也沒(méi)有通過(guò)tc的系統(tǒng)測(cè)試
          數(shù)字一大就超時(shí)了
          后面又時(shí)間再研究一下
          看看有沒(méi)有辦法在改進(jìn)

           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 閱讀(167) | 評(píng)論 (0)編輯 收藏
           
          TopCoder SRM 405 Level 2 1000
          一個(gè)理想的字符串,其中每個(gè)字母第一次出現(xiàn)的位置N,與這個(gè)字母在字符串中出現(xiàn)的次數(shù)M是相等的,求給定長(zhǎng)度的字符串中最小的一個(gè)理想字符串

          字符串長(zhǎng)度小于100
          相當(dāng)于去搜索1~100中的一組不同的數(shù)
          加起來(lái)等于長(zhǎng)度L
          同時(shí)每個(gè)數(shù)字都要小于等于比自己小的所有數(shù)的和加一
          因?yàn)長(zhǎng)比較小
          所以用深搜就可以了
          在這個(gè)過(guò)程中要注意深搜時(shí)候需要從大往小搜
          這樣才能滿足“最小的”結(jié)果
          搜索完之后的字符串構(gòu)建的步驟因?yàn)镾tringBuffer用的不熟練
          反而調(diào)試了很久
           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 閱讀(143) | 評(píng)論 (0)編輯 收藏
           
          TopCoder SRM 399 Level 2 1000
          http://www.topcoder.com/stat?c=problem_statement&pm=8758&rd=12171
          給定N和一個(gè)整數(shù)集合a,用不屬于a的3個(gè)整數(shù)相乘得出離N最近的整數(shù)

          N的范圍1~1000
          從小到大3重循環(huán)就可以解
          理論上的復(fù)雜度高達(dá)1000^3
          如果確實(shí)算一次我的電腦要跑到6秒
          不過(guò)其實(shí)當(dāng)乘積減去N已經(jīng)超過(guò)之前的差額時(shí)就可以break了
          所以計(jì)算量其實(shí)很小
          加上break算一次只要零點(diǎn)零幾秒
          另外的陷阱是循環(huán)如果只是1~1000是不行的
          有可能會(huì)用到比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 閱讀(127) | 評(píng)論 (0)編輯 收藏
           
          TopCoder SRM 397 Level2 1000
          http://www.topcoder.com/stat?c=problem_statement&pm=8746
          一個(gè)彩球集合,重量各不相同,給定容器大小如何帶回盡量多的彩球

          限制條件中彩球個(gè)數(shù)小于13
          因此用DP來(lái)計(jì)算復(fù)雜度為2^13*20*10是可以接受的
          這一題用memo方法更加合適因?yàn)闀?huì)有大量的數(shù)據(jù)不需要計(jì)算
          每一次都迭代計(jì)算所有未填的球
          把球放進(jìn)口袋或者直接開(kāi)始填下一袋
          DP三個(gè)參數(shù)是mask,剩余袋數(shù)和本袋剩余空間
           1import java.util.*;
           2import java.util.regex.*;
           3import java.text.*;
           4import java.math.*;
           5import java.awt.geom.*;
           6
           7public class CollectingMarbles
           8{
           9    int[][][] dic;
          10    int L;
          11    int[] mw;
          12    int bagNumber;
          13    int cap;
          14    
          15    public int mostMarbles(int[] marblesWeights, int bagCapacity, int numberOfBags)
          16    {
          17        L = marblesWeights.length;
          18        mw = marblesWeights;
          19        bagNumber = numberOfBags;
          20        cap = bagCapacity;
          21        dic = new int[1<<L][bagNumber+1][cap+1];
          22        for(int[][] a : dic)
          23            for(int[] b : a)
          24                Arrays.fill(b, -1);
          25        int ans = recur(0, bagNumber, cap);
          26        return ans == -1? 0 : ans;
          27    }

          28    
          29    private int recur(int mask, int bagNumber, int cur) {
          30        // TODO Auto-generated method stub
          31        if(bagNumber == 0)
          32            return 0;
          33        if(dic[mask][bagNumber][cur] > -1)
          34            return dic[mask][bagNumber][cur];
          35        dic[mask][bagNumber][cur] = 0;
          36        for(int i = 0 ; i < L ; ++ i){
          37            if((mask & (1 << i)) == 0 && mw[i] <= cur){
          38                dic[mask][bagNumber][cur] = Math.max(dic[mask][bagNumber][cur],
          39                        1+recur(mask|1<<i, bagNumber, cur-mw[i]));
          40                
          41            }

          42            dic[mask][bagNumber][cur] = Math.max(dic[mask][bagNumber][cur], 
          43                    recur(mask, bagNumber-1, cap));
          44        }

          45        
          46        return dic[mask][bagNumber][cur];
          47    }

          48}
          posted @ 2009-12-15 15:15 jav7er 閱讀(144) | 評(píng)論 (0)編輯 收藏
           
          TopCoder SRM 398 Level2 900
          http://www.topcoder.com/stat?c=problem_statement&pm=8160
          一組字符串,如何將其中一部分右移若干格,使得某一列的縱向恰好為要求的字符串,并且給出移動(dòng)最少的答案。

          這一題乍一看覺(jué)得很復(fù)雜
          有點(diǎn)像之前做過(guò)的吉他琴弦的那一題
          可是這個(gè)復(fù)雜度2^50是吃不消的
          但是這里有兩點(diǎn)不同
          一個(gè)是這里只能右移
          另一個(gè)很重要的是這個(gè)某一列將成為一個(gè)有參考意義的坐標(biāo)
          即用這個(gè)列號(hào)來(lái)遍歷 看答案在哪一列解答最少
          想通這一點(diǎn) 后面就很容易了
           1import java.util.*;
           2import java.util.regex.*;
           3import java.text.*;
           4import java.math.*;
           5import java.awt.geom.*;
           6
           7public class MatchString
           8{
           9    public int placeWords(String matchString, String[] matchWords)
          10    {
          11        List<ArrayList<Integer> > occur = new ArrayList<ArrayList<Integer> >();
          12        int L = matchWords.length;
          13        int end = 0;
          14        int start = Integer.MAX_VALUE;
          15        int i,j;
          16        for(i = 0 ; i < L ; ++ i){
          17            ArrayList<Integer> temp = new ArrayList<Integer>();
          18            char c = matchString.charAt(i);
          19            for(j = 0 ; j < matchWords[i].length(); ++ j){
          20                if(matchWords[i].charAt(j) == c)
          21                    temp.add(j);
          22            }

          23            if(temp.isEmpty()) return -1;
          24            occur.add(temp);
          25            if(matchWords[i].length() > end)
          26                end = matchWords[i].length();
          27            if(temp.get(0< start)
          28                start = temp.get(0);
          29        }

          30        int ans = Integer.MAX_VALUE;
          31        Outer:
          32        for(i = start; i <= end; ++ i){
          33            int tempans = 0;
          34            for(int k = 0 ; k < L; ++ k){
          35                j = 0;
          36                while(j < occur.get(k).size() && occur.get(k).get(j) <= i)
          37                    ++j;
          38                if(j == 0)
          39                    continue Outer;
          40                tempans += i - occur.get(k).get(j-1);                
          41            }

          42            ans = Math.min(ans, tempans);
          43        }

          44        return ans;
          45    }

          46}
          posted @ 2009-12-15 15:09 jav7er 閱讀(192) | 評(píng)論 (0)編輯 收藏
           
          主站蜘蛛池模板: 南投县| 新源县| 筠连县| 衢州市| 扬中市| 稷山县| 武穴市| 乐清市| 内乡县| 兰州市| 张家川| 巴彦淖尔市| 瑞丽市| 元朗区| 桃园市| 社会| 广西| 阿合奇县| 邯郸市| 金昌市| 昌乐县| 芦溪县| 天祝| 泸定县| 垦利县| 庆安县| 崇礼县| 平昌县| 乳山市| 阿勒泰市| 信丰县| 旬邑县| 宁安市| 南雄市| 馆陶县| 长春市| 邹平县| 乐至县| 嵩明县| 汉阴县| 博客|