• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Climber.pI的OI之路

            Through the darkest dark,may we see the light.

            #

            NOIp 2011 初賽備考

            [2010],74.5(+5+7-5), 市排10-
            [2007],49(+24+3+4), 過線8分
            [2006],75.5(+8), 市排0, 省排29
            [2009], 76.5, 市排10-
            [2008], 79(+17), 市排10-, 省排70+
            有兩套題是按照初賽模式模擬的, 連續(xù)思考還是有一些影響, 不妨在考場上先休息一下.

            1. 小數(shù)進(jìn)制轉(zhuǎn)換
            (1) n進(jìn)制 -> 10進(jìn)制
            (A1.2)16 = 10*16^1 + a^16^0 + 2*16^-1
            [長除法格式]例如,1020304從10進(jìn)制轉(zhuǎn)到7進(jìn)制:
            1020304 / 7 = 145757 r 5 ↑  => 11446435
             145757 / 7 =  20822 r 3 │
              20822 / 7 =   2974 r 4 │
               2974 / 7 =    424 r 6 │
                424 / 7 =     60 r 4 │
                 60 / 7 =      8 r 4 │
                  8 / 7 =      1 r 1 │
                  1 / 7 =      0 r 1 │
            http://zh.wikipedia.org/wiki/%E8%AE%B0%E6%95%B0%E7%B3%BB%E7%BB%9F#.E8.BF.9B.E5.88.B6.E8.BD.AC.E6.8D.A2
            (2) 10進(jìn)制 -> n進(jìn)制
            除n取余, 乘n取整
            http://www.cnblogs.com/keycode/archive/2010/10/26/1861265.html

            2. 邏輯表達(dá)式
            (1)考慮四種情況代值
            (2)利用邏輯代數(shù)公式化簡
            http://zh.wikipedia.org/wiki/%E9%80%BB%E8%BE%91%E4%BB%A3%E6%95%B0
            http://202.201.48.18/jpkc/2006/szdzjs/shoukejiaoan/0001.htm

            3.數(shù)據(jù)結(jié)構(gòu)
            (1)表達(dá)式樹
            [中綴] (a + b) * c + d * c
            (((a + b) * c) + (d * c))
            [前綴] +(*(+(a b) c) * (d c))
            + * + a b c * d c
            [計(jì)算方法1] 壓棧(前綴 -> 從后向前), 即彈出順序
            [計(jì)算方法2] 括號(opt后) -> 中綴
            (2)二叉樹中根遍歷
            根據(jù)先根遍歷和后根遍歷畫出樹, 找到樹中的不變部分, 分析不確定部分的情況(任意與否).

            4.計(jì)算機(jī)史
            [計(jì)算機(jī)領(lǐng)域先驅(qū)者]
            http://zh.wikipedia.org/wiki/Category:%E8%AE%A1%E7%AE%97%E6%9C%BA%E9%A2%86%E5%9F%9F%E5%85%88%E9%A9%B1%E8%80%85

            5.常識(shí)
            [面向?qū)ο蟪绦蛟O(shè)計(jì)]http://zh.wikipedia.org/wiki/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1
            [ALU]http://zh.wikipedia.org/wiki/ALU
            [Hash]http://zh.wikipedia.org/wiki/%E6%95%A3%E5%88%97%E8%A1%A8
            [IPv6]http://zh.wikipedia.org/wiki/Ipv6
            [RAM]http://zh.wikipedia.org/wiki/%E9%9A%8F%E6%9C%BA%E5%AD%98%E5%8F%96%E5%AD%98%E5%82%A8%E5%99%A8
            [CPU]http://zh.wikipedia.org/wiki/CPU
            [寄存器]http://zh.wikipedia.org/wiki/%E5%AF%84%E5%AD%98%E5%99%A8
            [馮諾依曼結(jié)構(gòu)]http://zh.wikipedia.org/wiki/%E8%8C%83%E7%B4%90%E6%9B%BC%E6%9E%B6%E6%A7%8B
            [標(biāo)記語言]http://zh.wikipedia.org/wiki/%E7%BD%AE%E6%A0%87%E8%AF%AD%E8%A8%80
            [自然語言]http://zh.wikipedia.org/wiki/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80

            6.運(yùn)算符優(yōu)先級
            http://hi.baidu.com/xyh2007/blog/item/b2cd4b60c5dfa145eaf8f8b3.html
            [記憶]去掉一個(gè)最高的,去掉一個(gè)最低的,剩下的是一、二、三、賦值。雙目運(yùn)算符中,順序?yàn)樗阈g(shù)、關(guān)系(> >= < <=高于== !=)和邏輯(&& ||),移位和邏輯位(&^|)插入其中。   

            7.遞推關(guān)系
            (1)第二類stirling數(shù) s(n,k) = s(n-1, k-1) + k*s(n-1, k)
            [直觀解釋]前面一種就是新開一組, 后面一種是前面分了k組, 我隨便找一組丟進(jìn)去.
            (提示:先固定一個(gè)數(shù),對于其余的5個(gè)數(shù)考慮S(5,3)與 S(5,2),再分這兩種情況對原固定的數(shù)進(jìn)行分析)-> 討論一個(gè)數(shù)

            8.補(bǔ)碼表示法
            [內(nèi)容]http://www.cnblogs.com/tenghoo/archive/2008/06/01/1211663.html
            [動(dòng)機(jī)]http://blog.163.com/fan_yishan/blog/static/476922132008697421719/
            a-b = a+(b % 2^n), 即對2^n取模.
            N * = 2^n - N = [2^4](base10) - 0101 = 10000(base2) - 0101 = 1011
            [補(bǔ)碼/二補(bǔ)數(shù)]http://zh.wikipedia.org/wiki/%E4%BA%8C%E8%A3%9C%E6%95%B8

            9.排序算法
            [穩(wěn)定]插入排序、冒泡排序、歸并排序、分配排序(桶式、基數(shù))
            [不穩(wěn)定的]直接選擇排序、堆排序、shell排序、快速排序都是不穩(wěn)定的排序算法。
            [穩(wěn)定排序]http://www.jpk.pku.edu.cn/pkujpk/course/sjjg/chapter7/01/05.html
            [排序原理]http://hi.baidu.com/cuifenghui/blog/item/0587932b039557f9e7cd4051.html
            [5個(gè)數(shù)7次比較]
            1. [構(gòu)造排序樹]http://topic.csdn.net/t/20031207/21/2537867.html
            2. 歸并排序(拆分為2 - 3)
            3. 從排列角度考慮, log2(n!)上取整
            http://zhidao.baidu.com/question/71416468.html

            10.圖論
            (1)二分圖判定
            [定理]無向圖G為二分圖的充要條件是, G至少有兩個(gè)頂點(diǎn), 且其所有回路的長度均為偶數(shù).
            (2)哈密頓圖
            [定義]由指定的起點(diǎn)前往指定的終點(diǎn),途中經(jīng)過所有其他節(jié)點(diǎn)且只經(jīng)過一次.
            http://zh.wikipedia.org/wiki/%E5%93%88%E5%AF%86%E5%B0%94%E9%A1%BF%E5%9B%BE

            11.閱讀程序注意事項(xiàng)
            (1)對程序段進(jìn)行等價(jià)變換
            (2)看清if的條件(比較符號看翻, 忽略括號)
            (3)兩位數(shù)以上乘法豎式計(jì)算兩遍(即改變順序) -> 特別注意!!!!!!!!!
            (4)注意函數(shù)名縮寫(hpsrt)和特征語句(j = k + k) -> 07的堆排(不斷更新大根堆)沒看出來
            (5)對于很惡心的模擬題: 列表法(三維可以在水平方向在加列, 不妨用其他顏色的筆, 或者鉛筆指出指針)

            12.完善程序注意事項(xiàng)
            (1)注意區(qū)別遞歸函數(shù)參數(shù)的0和1,以及遞歸是參數(shù)是否需要改變(如果在函數(shù)中改變了, 很可能不用)
            (2)注意邊界條件(通過交換確定, 還是通過枚舉確定)
            (3)遇到比較熟悉, 但是忘得差不多的算法, 一開始不要糾纏, 最后再斟酌
            (4)注意函數(shù)類型, 比如void main(), 不要寫return 0;
            (5)對于for循環(huán), 弄清楚循環(huán)變量i或j代表什么(結(jié)合題目分析)

            13.負(fù)數(shù)取模
            [定義]x % y = x - y*(x/y);
            需要注意, 下取整的定義和數(shù)學(xué)取整的定義不同.
            [這里是分析]http://chinakite.iteye.com/blog/25142

            14.指針(參照<C++ Primer Plus>)
            (1)定義
            int a, *b; //這里表示的都是值, &a 和 b 都是地址
            int *a = &k; //這么解釋 int * a = &k; 即先對地址a賦值
            (2)分析
            因而兩種swap可以解釋(只有交換值才有效):
            void swap(int &x, int &y){int k = x; x = y; y = k;} //傳入地址, 交換值
            void swap(int *x, int *y){int k = *x; *x = *y; *y = k;} //傳入值, 交換值
            void swap(int *x, int *y){int *k = *x; *x = *y; *y = *k;} //傳入值, 交換值, 但k是隨機(jī)地址, 可能寫到不能寫的位置上
            void swap(int *x, int *y){int *k = x; x = y; y = k;} //傳入值, 交換地址
            (3)注意事項(xiàng)
            int * fellow; //這里的fellow是隨機(jī)地址, 必須使用int *fellow = new int;來初始化
            *fellow = 123456;
            (4)應(yīng)用: 動(dòng)態(tài)數(shù)組(略)

            posted @ 2011-10-15 11:27 Climber.pI 閱讀(416) | 評論 (0)編輯 收藏

            Problem List (9.7 ~ 9.29)

            9.7

            NOIp03 network[拓?fù)渑判?模擬], 2h
            注意讀題, 題目中給出公式C[i] = Σ(W[j][i]*C[j]) - U[i](C[j] > 0), 特別注意成立條件.
            把題目中給出的DAG反向, 對于C[i], 計(jì)算所有i的后繼即可. 僅按照編號順序輸出大于零的神經(jīng)元, 題目描述有誤.
            *注意分析題目, 不要急于敲程序.
            *對于DAG上的拓?fù)渑判騿栴}, 一類如本題和project, 直接利用圖; 另一類如frameup, 要輸出完整路徑, 需要按照定義消去點(diǎn).

            9.8

            NOIp01 Car的旅行路線[預(yù)處理+最短路], 2h
            1.構(gòu)造矩形, 利用點(diǎn)積判斷垂直, 利用平行四邊形坐標(biāo)關(guān)系求第四點(diǎn)坐標(biāo)
            2.構(gòu)造圖, 分別處理矩形內(nèi) 和 不同矩形的情況
            3.Floyd最短路, 對始末矩形判斷最小值(此處假設(shè)始末矩形不同)
            *需要特判始末矩形相同的情況
            *注意double的強(qiáng)制轉(zhuǎn)換

            9.10

            Tyvj Sept月賽(2.5h)
            badgers, 0/1背包, 預(yù)計(jì)AC.
            tree, 排序+亂搞, 看錯(cuò)題.
            沒有考慮深度>2的樹, 似乎需要用到并查集.
            number, 模擬, 預(yù)計(jì)30
            顯然top>=2^(n-1)
            register, 沒寫, 只會(huì)30.
            估計(jì)150. -> 50;

            9.14

            badgers, 二分+貪心, 40min, 1Y
            對于n只badgers, 需要的食物總量tot = Σ(H[i] + (n-1)*G[i]), 二分求解即可.
            *讀題!
            *寫出關(guān)鍵函數(shù)

            tree, kruskal變形
            利用和kruskal一樣的思想.
            1. 對于每個(gè)點(diǎn)A分別屬于各自的集合
            2. 對邊排序
            3. 按順序合并集合, ans += (num[i]*num[j]-1)(c[i]+1)+c[i];

            9.26

            NOIp10 關(guān)押罪犯[二分+BFS判重], 3h
            1. 用鄰接表存儲(chǔ)邊, 可以抽象為addEdge函數(shù)
            2. 二分最大值
            3. check函數(shù)用BFS染色判重, 枚舉每一個(gè)點(diǎn)進(jìn)行BFS.
            *判重可以將數(shù)組初始化為-1, 然后判斷隊(duì)列中每個(gè)點(diǎn)的顏色是否為-1, 可以避免使用vis數(shù)組.
            [注意事項(xiàng)]
            1. 題目中僅給出無向邊
            2. 標(biāo)記節(jié)點(diǎn)是否已讀 -> 利用color即可
            3. 遍歷所有連通分量 -> 枚舉每個(gè)點(diǎn)即可, 不必記錄所有滿足條件的邊上的端點(diǎn)

            9.27

            NOIp10 關(guān)押罪犯, 30min, AC
            1. 鄰接表不熟
            2. 二分打錯(cuò)
            3. 不理解gXX程序判重原理
            [原理]和我的做法一樣, 不同的是gXX程序避免了對每個(gè)點(diǎn)重復(fù)染相同顏色, 因而需要進(jìn)行染色的點(diǎn)必然未訪問.

            9.28

            NOIp10 關(guān)押罪犯, 10min, AC
            1. 鄰接表first沒有初始化
            2. 邊界打錯(cuò)

            NOIp10 烏龜棋[DP], 20min, AC
            注意到已通過路徑可以用a+2*b+3*c+4*d表示, 因而設(shè)置狀態(tài)為f[a][b][c][d];
            f[a][b][c][d] = max{f[a-1][b][c][d], f[a][b-1][c][d], f[a][b][c-1][d], f[a][b][c][d-1]} + A[a+2*b+3*c+4*d];
            *注意從第一個(gè)格子開始, 故A[0..n-1], f[0][0][0][0] = A[0], 注意下標(biāo)實(shí)際意義.
            *去年寫錯(cuò)方程主要是沒有考慮下標(biāo)間練習(xí), 直接套用NOIp05過河方程. 對于相似的題目, 最重要的是找到不同的部分.

            9.29

            NOIp08 雙棧排序[DFS+剪枝], 50min, 30
            1. dfs狀態(tài): (操作序列長度, 已輸入序列長度, 已輸出序列長度, 棧1深度, 棧2深度)
            2. 可行性剪枝:
            (1) 優(yōu)先彈出符合條件元素(即等于 已輸入序列長度+1) 
            (2) 找到解后立即退出
            *標(biāo)準(zhǔn)做法的構(gòu)造非常神奇, 解釋動(dòng)機(jī)無能. -> 觀點(diǎn)來自gXX

            posted @ 2011-10-01 21:53 Climber.pI 閱讀(208) | 評論 (0)編輯 收藏

            USACO Training Chapter 4 ~ 6 Summary

            Section 4.1

            2010.08.26 TEXT Optimization Techniques

            2010.10.19 PROB Beef McNuggets 多重背包+裴蜀定理

            2011.08.07 PROB Fence Rails DFS+剪枝

            2011.03.24 PROB Fence Loops DFS / 最小環(huán)(Floyd)

            2011.08.10 PROB Cryptcowgraphy DFS+剪枝+字符串處理

            Section 4.2

            2011.08.10 TEXT "Network Flow" Algorithms

            2011.03.19 PROB Drainage Ditches 最大流(Edmonds-Karp)

            2011.03.19 PROB The Perfect Stall 最大流 / 二分圖最大匹配(Hungary)

            2011.08.10 PROB Job Processing 二分+貪心

            2011.08.11 PROB Cowcycles DFS+剪枝

            Section 4.3

            2011.08.11 TEXT Big Numbers

            2011.08.08 PROB Buy Low, Buy Lower DP+統(tǒng)計(jì)方案數(shù)+高精度

            2011.08.12 PROB The Primes DFS+剪枝

            2011.08.12 PROB Street Race DFS判斷連通性

            2011.08.11 PROB Letter Game 枚舉+優(yōu)化

            Section 4.4

            2011.08.13 PROB Shuttle Puzzle 數(shù)學(xué) / BFS

            2011.08.13 PROB Pollutant Control 最小割

            2011.08.16 PROB Frame Up 拓?fù)渑判?/span>

             Section 5.1

            2011.08.17 TEXT Convex Hulls

            2011.08.17 PROB Fencing the Cows 凸包(Graham-Scan)

            2011.08.16 PROB Starry Night Floodfill + 模擬

            2011.08.13 PROB Musical Themes 二分 / DP

            Section 5.2

            2011.08.17 PROB Snail Trail DFS

            2011.08.17 PROB Electric Fences 模擬退火 / 局部搜索 / 隨機(jī)化搜索

            2011.08.17 PROB Wisconsin Squares DFS

            Section 5.3

            2011.08.17 TEXT Heuristics & Approximate Searches

            2011.08.18 PROB Milk Measuring DFS-ID + DP / DP

            2011.08.18 PROB Window Area 矩形切割 + 模擬

            2011.08.18 PROB Network of Schools 強(qiáng)連通分量(Tarjan)

            2010.08.19 PROB Big Barn DP

            Section 5.4

            2011.08.18 PROB All Latin Squares DFS+剪枝 / DFS+置換群

            2011.08.19 PROB Canada Tour DP / DP+刷表法

            2011.08.20 PROB Character Recognition 統(tǒng)計(jì) + DP

            2011.08.19 PROB Betsy's Tour DFS+剪枝 / SCDP

            2011.08.18 PROB TeleCowmunication 最小割

            Section 5.5

            2011.08.21 PROB Picture 離散化 + 掃描 / 線段樹

            2011.08.20 PROB Hidden Passwords 枚舉+優(yōu)化 / 最小后綴

            2011.08.21 PROB Two Five Cantor展開 + DFS

            Section 6.1

            2011.08.21 PROB Postal Vans DP / SCDP

            2011.08.21 PROB A Rectangular Barn DP(懸線法)

            2011.08.21 PROB Cow XOR 枚舉+優(yōu)化

            大致學(xué)習(xí)了這些東西:

            1. DFS, 以及常見的優(yōu)化技巧

            2. 二分法轉(zhuǎn)化為判定性問題

            3. <string>的使用

            4. 離散化思想

            5. Tarjan算法(強(qiáng)連通分量)

            6. 懸線法求最大子矩陣

            7. Hungary算法(棋盤覆蓋, 最小路徑覆蓋)

            8. 拓?fù)渑判虻腄FS實(shí)現(xiàn)

            9. DP的刷表法實(shí)現(xiàn)(白書P172) 

            10. Edmonds-Karp算法

            11. Graham-Scan算法求凸包, 水平線實(shí)現(xiàn)

            個(gè)人以為對于NOIp來說, USACO Training Chapter4之后的內(nèi)容的主要價(jià)值在于訓(xùn)練調(diào)試能力, DFS+剪枝的題目非常多, 對于訓(xùn)練暴搜來說是很好的教材. 算法上的話, Chapter4以后的NOIp新內(nèi)容只有二分法和DFS優(yōu)化技巧, 但是對于算法組合能力的要求有了進(jìn)一步提升, 只有基礎(chǔ)非常扎實(shí)才能在短時(shí)間內(nèi)AC題目.

            不過目前的調(diào)試能力仍然有限, 不太復(fù)雜的DFS可能需要30 ~ 50min, 較為復(fù)雜的DFS可能需要2~3h甚至更長的時(shí)間才能調(diào)試通過. 對于NOIp來說還是太長了, 簡單DFS應(yīng)該在20min內(nèi)調(diào)試成功, 復(fù)雜一些也應(yīng)該在1h內(nèi)調(diào)試成功. 這方面還需要進(jìn)一步訓(xùn)練.

            這次寫USACO Training跳過了4道題, 分別是1.4的某道矩形, 3.4.1的計(jì)算幾何, 4.4.2和5.4.5的兩道最小割. 如果日后打算參加GDKOI/GDOI的話, 再彌補(bǔ)網(wǎng)絡(luò)流/SCDP/高級數(shù)據(jù)結(jié)構(gòu)(Trie/線段樹/SBT/樹狀數(shù)組)這方面的內(nèi)容. Chapter5和Chapter6的幾道題還是很難理解題解, 也沒有掌握.

            不管怎么說, 我比一年前還是強(qiáng)了很多.

            posted @ 2011-08-23 13:26 Climber.pI 閱讀(491) | 評論 (0)編輯 收藏

            Problem List (8.13 ~ 8.21)

            8.13


            prime3[DFS + 手動(dòng)指定搜索順序], 4h, 0.1s左右出解
            1.構(gòu)造所有五位素?cái)?shù), 可以先做一個(gè)313以內(nèi)的素?cái)?shù)表, 試除即可. 注意素?cái)?shù)末尾不是偶數(shù)和0.
            *官方題解中枚舉6n-1和6n+1, 同時(shí)判斷末位5和0, 從素?cái)?shù)7開始枚舉即可, 枚舉量進(jìn)一步減少
            2.手動(dòng)指定搜索順序, 對于每種情況分別處理, 代碼很長. 對角線優(yōu)先, 末尾數(shù)組優(yōu)先(顯然素?cái)?shù)末尾數(shù)字只能是1\3\7\9)
             0 21 18 22  5
            12  2 13  8  9
            16 23  3 24 10
            14  7 15  4 11
             6 19 17 20  1
            大致分為幾種情況:
            1)非末位. 邊界條件是 0 <= i <= min{sum(除去已使用位), 9}
            2)末位. 邊界條件是i = 1, 3, 7, 9(i <= sum)
            3)可計(jì)算位(即該行或列或?qū)蔷€已經(jīng)填了4個(gè)數(shù)). sum < 10, 判斷是否為素?cái)?shù), dfs下一層時(shí), sum-下一層已填充位置.
            4)對于由情況3)轉(zhuǎn)移而來的狀態(tài), 需要檢查sum >= 0
            *可以把情況1)和2)分別合并, 利用數(shù)組指定順序亦可(代碼長度可能變化不大)
            *官方題解在這里以行\(zhòng)列\(zhòng)對角線為單位填數(shù), 需要預(yù)處理某些位為某些數(shù)的素?cái)?shù).
            3.對保存的結(jié)果進(jìn)行排序, 利用qsort間接排序即可.
            *NOCOW上有人寫15重for循環(huán), 效率比這個(gè)低10倍. 但是15重for加上縮進(jìn)實(shí)在不好看.

            race3[DFS判斷連通性], 40min
            第一問, 去掉每個(gè)點(diǎn)后判斷是否能夠到達(dá)終點(diǎn), 利用DFS+vis數(shù)組標(biāo)記即可.
            第二問, 第二問是第一問答案的子集. 從原點(diǎn)(標(biāo)記A不可訪問)和第一問某個(gè)點(diǎn)A分別DFS, 如果不存在某點(diǎn)在兩次同時(shí)被訪問, 那么滿足題意.
            證明: 假設(shè)第二問不是第一問的子集, 那么不經(jīng)過第二問中某個(gè)點(diǎn), 必然可以到達(dá)終點(diǎn), 與題目中對于分割的定義矛盾.
            *用Floyd判斷連通性亦可(有向圖傳遞閉包).

            shuttle[BFS/數(shù)學(xué)], 4h
            1)BFS做法(n <= 7)
            1.利用位運(yùn)算保存狀態(tài), 1表示'W', 2表示'B'或空格, 附加k表示空格所在位
            2.按照字典序轉(zhuǎn)移狀態(tài)(共4種方式), k的方向可以任意理解, 不影響結(jié)果. k從0開始, 顯然W只向右, B只向左.
            *在草稿紙上寫好狀態(tài)轉(zhuǎn)移的具體代碼(if部分), 注意變量
            *讀題, 一開始認(rèn)為棋盤長度不超過12于是就BFS, 實(shí)際上棋盤長度不超過25, 位運(yùn)算保存狀態(tài)會(huì)爆內(nèi)存. 此外輸出限制每行20個(gè)數(shù)字.
            2)數(shù)學(xué) by NOCOW
            我們憑借極其敏銳的眼光發(fā)現(xiàn)這組序列為
            4 35 642 1357 642 35 4 (n=3,樣例)
            5 46 753 2468 97531 2468 753 46 5 (n=4)
            即長度為1,2,3,4,...,n,n+1,n,...,4,3,2,1這樣的2n+1組等差序列
            我們討論第1~n+1組序列,這些序列滿足
              *公差的絕對值為2
              *奇數(shù)組為降序列,偶數(shù)組為升序列
              *對于第i組(1<=i<=n+1),若為奇數(shù)組則首項(xiàng)為n+i,偶數(shù)組則首項(xiàng)為n-i+2
            對于第n+2~2n+1組,可以由對稱性求出.
            *官方題解做法類似數(shù)學(xué)做法, 觀察后得出每次都是空格向右移動(dòng)2格, 直到不能移動(dòng)(如果不能向右移動(dòng)1格的話轉(zhuǎn)向)或者達(dá)到狀態(tài).
            *如果輸出字典序最小解, 不妨找規(guī)律; 如果輸出所有解, 只能搜索.

            milk6[最小割+貪心], 按計(jì)劃cheat.

            frameup[拓?fù)渑判騗
            1.構(gòu)造有向圖. 在讀入圖的同時(shí)計(jì)算每種矩形的坐標(biāo)邊界, 然后按照邊界遍歷, 若矩形A上存在B, 則G[A][B] = 1.
            2.拓?fù)渑判虿⑤敵? 注意到這里并沒有明顯層次性, 答案可能遠(yuǎn)遠(yuǎn)超過所得序列長度. 如果標(biāo)記層次的話, 若圖中指向復(fù)雜, 那么會(huì)少輸出一部分答案(如測試點(diǎn)7).
            *一開始沒有看出來是拓排, 一門心思想怎么DFS.
            *打錯(cuò)變量調(diào)了1h, 沒有看出來輸出序列的不同浪費(fèi)了1h. -> 開始的分析非常重要, 邊寫邊改時(shí)間成本太高.

            8.14

            theme[二分], 1.5h, O(N^3logN)
            1.對序列做差, d[i] = A[i+1] - A[i].
            2.二分求最大值. 注意l=m+1, 可能存在m為最大值的情況, 所以需要check(l).
            3.分別枚舉兩個(gè)序列的開端(序列1開端為i, 序列2開端為i+l+1), 如果相同, 繼續(xù)比較.
            *數(shù)組開小, 導(dǎo)致詭異錯(cuò)誤 -> 讀題!!!, 20min
            *注意編寫的程序前分析邊界情況 -> 1h

            8.15

            調(diào)教laptop.

            8.16

            frameup[拓?fù)渑判騗, 20min -> 參照 北極南天星 的題解, 意簡言賅
            構(gòu)圖這里不再贅述. 注意到題目要求輸出拓?fù)湫蛄? 長度一定, 并不像DP中出現(xiàn)明顯層次性.
            dfs狀態(tài)(當(dāng)前序列長度), 按照定義做: 每次找入度為0的點(diǎn)u, 然后將于此點(diǎn)存在邊的點(diǎn)v入度-1. 直到所有點(diǎn)都在序列中.
            *dfs按照字母升序搜索, 即滿足題目順序要求.
            *構(gòu)圖統(tǒng)計(jì)每個(gè)點(diǎn)u入度時(shí)注意判重, 存在多個(gè)點(diǎn)滿足條件.

            theme[DP], O(N^2)
            f[i][j] = max{f[i+1][j+1]}(A[i+1]-A[i] == A[j+1]-A[j]) + 1
            f[i][j]表示以A[i]和A[j]為起點(diǎn)的序列的最大長度, 以j-i為階段, 注意f[i][j]<=j-i. 注意到狀態(tài)之間存在依賴性, 各階段間不存在依賴性, 只需保存當(dāng)前狀態(tài). 不斷更新答案即可.
            *不能直接二分, 答案可能小于j-i, 無法寫判定函數(shù) -> 如果對于每個(gè)j-i的長度序列單調(diào)不下降的話還是可以二分.

            8.17

            starry[floodfill+模擬], 4h
            讀入圖, 對每個(gè)點(diǎn)進(jìn)行floodfill; 如果存在星座, 那么和之前的星座進(jìn)行判重; 不重復(fù)的話, 利用數(shù)組st0記錄當(dāng)前星座. 否則改變標(biāo)號.
            判重首先判斷 長度 和 星體個(gè)數(shù)(只利用這兩點(diǎn)可以過4個(gè)點(diǎn)), 然后直接模擬即可. 在floodfill過程中記錄坐標(biāo)極值, 然后提取矩形, 和st0中星座比較.
            比較需要用到順時(shí)針向右轉(zhuǎn)90度和水平翻轉(zhuǎn), 坐標(biāo)變換分別是(tx-x, y)和(y, tx-x), 可以畫圖觀察.
            *一開始沒有考慮如何判重, 想了1h
            *沒有考慮同一矩形內(nèi)存在多個(gè)相同星座, 浪費(fèi)0.5h

            fc[凸包(Graham-Scan, 水平序?qū)崿F(xiàn))], 1h, 參考黑書
            1.以縱坐標(biāo)為第一關(guān)鍵字, 橫坐標(biāo)為第二關(guān)鍵字, 對坐標(biāo)升序排序.
            2.左鏈掃描, 從1到n. 如果棧內(nèi)存在超過兩個(gè)元素, 那么叉積判斷是否>180°(即cross<=0), 滿足的話彈出棧頂元素(利用while). 將當(dāng)前點(diǎn)加入棧.
            3.右鏈掃描, 從n-1到1. 判斷同上.
            4.計(jì)算周長. 加入初始點(diǎn)和末端點(diǎn)距離, 依次加入棧中元素.
            *利用棧表示凸包序列

            snail[DFS], 50min
            讀入路障坐標(biāo)(x,y)標(biāo)記為-1, 其他值為1; DFS過程中檢查下一格是否可行, 若不可行, 如果是邊界或路障可以轉(zhuǎn)向. 記錄最大值.
            *注意當(dāng)前標(biāo)記在DFS后清除, 已路過格不可轉(zhuǎn)向; 障礙縱坐標(biāo)可能不是一位, 讀入橫坐標(biāo)后標(biāo)記該為為'0', 利用sscanf讀入即可.
            *想起了去年NOIp第四題, 只有半個(gè)小時(shí), 但是寫了floodfill卻調(diào)不出來. 心里沒底, 仿佛這是看RP的事情, 今天半個(gè)小時(shí)的時(shí)候發(fā)生了同樣的事情, 務(wù)必加長算法設(shè)計(jì)時(shí)間.

            wissqu[DFS] -> cheat
            題目給出了每種牛的個(gè)數(shù), 實(shí)質(zhì)上就是帶限制的全排列, 可行性剪枝很多, 代碼大概要100+行.
            *不過這題只有一個(gè)測試數(shù)據(jù), 就是樣例 -_-

            8.18

            fence3[局部搜索], 1h
            標(biāo)準(zhǔn)做法是模擬退火, 或者隨機(jī)化搜索. 基本思想是逐漸加精度(官方題解也這么寫).
            首先搜索所有整數(shù)坐標(biāo), 記錄最小距離和當(dāng)時(shí)坐標(biāo); 然后在此坐標(biāo)±1范圍內(nèi)搜索最小值, 注意增量dx/dy要初始化為0(這時(shí)不會(huì)更新最小值).

            bigbrn[DP], 30min
            f[i][j]表示以(i, j)為右下方頂點(diǎn)的正方形的最大邊長
            f[i][j] = min(f[i-1][j], f[i][j-1], f[i-1][j-1]) + 1
            初始化 f[i][j] = 1; 若(i, j)有障礙, 則f[i][j] = 0, 且該點(diǎn)不進(jìn)行dp

            window[鏈表(字符串實(shí)現(xiàn)) + 矩形切割(10行)], 3h
            對于操作w/t/b/d, 維護(hù)操作序列order, 利用<string>實(shí)現(xiàn). 注意string str(&a[i], &a[j])對應(yīng)區(qū)間為[i, j). 構(gòu)造小數(shù)據(jù)調(diào)試即可.
            對于操作s, 利用矩形切割, 逆序添加操作序列order中矩形(可以同時(shí)維護(hù)面積). 實(shí)現(xiàn)非常簡單, 首先對判斷是否被已有矩形覆蓋(x2 < x1), 然后分成四部分添加未被覆蓋部分.
            注意到數(shù)據(jù)中s操作可以連續(xù), 不妨利用char記錄上一操作, 可以避免一些矩形切割.
            *這題想想會(huì)覺得頭疼, 但是實(shí)現(xiàn)非常簡單(ctypcow實(shí)現(xiàn)非常麻煩). 題目并不難, 很明顯下午看題的時(shí)候高估了實(shí)現(xiàn)難度. 不要給自己制造"難題".
            *提交程序中對stdout輸出過多同樣會(huì)造成崩潰

            8.19

            milk4[DFS-ID + DP], 45min
            利用DFS-ID枚舉桶(即枚舉r-組合), 然后DP判斷能否裝滿.
            f[j] |= f[j-ans[i]](完全背包, 不考慮背包數(shù))
            初始化f[0] = 1, 其他為0; f[i]表示可以量出i夸脫的牛奶
            *打錯(cuò)變量(DFS/DP), 應(yīng)該首先靜態(tài)差錯(cuò), 而不是上數(shù)據(jù).
            *有純dp做法, 記錄方案很繁瑣.

            schlnet[強(qiáng)連通分量(Tarjan)], 1h
            利用鄰接表存儲(chǔ)圖, 利用Tarjan尋找強(qiáng)連通分量(BYVoid有個(gè)很好的教程, 主過程19行).
            第一問是最小點(diǎn)基, 對求得的所有強(qiáng)連通分量進(jìn)行縮點(diǎn), 入度為0的點(diǎn)的個(gè)數(shù)即為答案.
            第二問為min(入度為0的點(diǎn)的個(gè)數(shù), 出度為0的點(diǎn)的個(gè)數(shù)), 需要注意只有一個(gè)點(diǎn)的時(shí)候需要特判.
            [Tarjan]入棧\時(shí)間戳 -> 遍歷相鄰邊 -> 未遍歷點(diǎn)遍歷 -> 更新LOW -> LOW是否等于DFN -> 出棧標(biāo)記SCC

            latin[DFS + 數(shù)學(xué)], 1h
            注意第一行題目中已確定, 最后一行和最后一列同樣可以推算, 因而只需枚舉中間(n-1)*(n-2)方格即可. 可以規(guī)定第一列升序, 這樣一來計(jì)算量只是原來的1/(n-1)!, 可以過六組. 第七組需要cheat, 運(yùn)行時(shí)間大概1min左右(可能常數(shù)可以少一些). 標(biāo)準(zhǔn)做法是置換群.(std理解不能)

            telecow[網(wǎng)絡(luò)流], 按計(jì)劃cheat

            besty[DFS], 1h, N=7 15s
            按照題意進(jìn)行DFS, 有幾個(gè)優(yōu)化.
            1.當(dāng)點(diǎn)的可選擇方向?yàn)?時(shí), 用floodfill判斷圖內(nèi)未填充點(diǎn)是否可以互相到達(dá), 不能到達(dá)則剪枝.
            2.如果經(jīng)過點(diǎn)(1,n), 但填充順序k不滿足題意, 剪枝.
            3.內(nèi)層檢查擴(kuò)展節(jié)點(diǎn)是否符合題意(常數(shù)優(yōu)化).
            4.判斷某點(diǎn)到(1,n)距離是否小于n*n-k(加了反而更慢).
            *可以輸出狀態(tài)觀察歸納不可解狀態(tài)的共性, 然后剪枝. -> by dd_engi
            *據(jù)說可以使用著名的cdqDP..
            -> 參考黑書P184, 3h
            1.圖中必須沒有孤立區(qū)域, 即上文優(yōu)化1, 這里僅討論■□■的情況.
            2.搜索過程中, 除被搜索點(diǎn)和目標(biāo)點(diǎn)外, 其他點(diǎn)至少有兩個(gè)點(diǎn)與之相連. 可以利用數(shù)組link[i][j]記錄(i, j)的連通情況.
            3.如果移動(dòng)方向上前一個(gè)點(diǎn)未被遍歷, 左邊點(diǎn)未被遍歷, 且左前方點(diǎn)已被遍歷時(shí), 剪枝. 右側(cè)同理.
            利用剪枝1和2以及前文剪枝2, 在本地N=7需要2.3s, 加上剪枝3在本地需要1.9s, 在USACO卡時(shí)AC.
            *一個(gè)技巧, 可以預(yù)先表示行列編號為0和n+1的點(diǎn)已讀, 可以避免對越界的討論.

            tour[雙進(jìn)程DP/費(fèi)用流/刷表法], 3h, O(N^3)
            狀態(tài)想對了, f[i][j]表示兩個(gè)人分別從起點(diǎn)出發(fā)到達(dá)城市i\j所經(jīng)過的城市數(shù).
            一開始認(rèn)為方程是f[i][j] = max{f[i.prev][j], f[i][j.prev], f[i.prev][j.prev]+1}, 覺得不太對, 就去查題解.
            北極天南星給出的方程是 f[i][j] = max{f[j][k], f[k][j]} + 1
            規(guī)定對于任意狀態(tài)f[i][j], i > j, 需要注意f[j][k]\f[k][j]必須計(jì)算過. 初始化f[1][1] = 1, 其余為0.
            *利用strcmp比較字符串即可, memcmp似乎某些情況下會(huì)出錯(cuò).
            *這題和NOIp 08傳紙條的主要區(qū)別: 這題是無向圖, 而傳紙條是矩陣. 因而轉(zhuǎn)移方式不同.
            [故事] by BYVoid
            這是加拿大IOI93的一道原題。在WC2008中聽吳教授說道,當(dāng)時(shí)參加IOI的選手沒有人了解動(dòng)態(tài)規(guī)劃,對這道題束手無策。選手們都用上了最復(fù)雜的搜索技巧,有人還寫了雙向搜索,可是都沒有通過。回國后開始研究,最終提出了動(dòng)態(tài)規(guī)劃這一算法設(shè)計(jì)方法,于是動(dòng)態(tài)規(guī)劃變成了之后競賽出題的熱點(diǎn)。

            8.20

            hidden[字符串], 2.2h
            最初的做法很猥瑣, 按題意模擬, 記錄最小字典序串的口令. 第8個(gè)點(diǎn)TLE了, 大概都要5s左右.
            進(jìn)一步的修正記錄了每個(gè)字母每次出現(xiàn)的位置, alpha[i][0]表示出現(xiàn)次數(shù), 類似鄰接表. 只處理字典序最小出現(xiàn)次數(shù)非零的字母, 第10個(gè)點(diǎn)TLE了.
            更進(jìn)一步, 對于串中若干個(gè)連續(xù)的該字母, Count[j]表示alpha[i][j]開始, 由該字母組成的最長連續(xù)串. 只處理第一個(gè), 一開始沒有考慮環(huán)狀, 第11個(gè)WA了.
            *處理環(huán)狀的必要條件是, alpha[i][alpha[i][0]] + 1 == n;
            *對于復(fù)雜度估計(jì)不周, O(N)的常數(shù)太大所以掛了, 之后修正沒有考慮環(huán)狀情況, 卡了1h.
            *秒殺做法包括最小表示法\后綴數(shù)組\類KMP\最小后綴, 有空應(yīng)該學(xué)一下著名的KMP算法

            cowxor[?]
            很容易聯(lián)想到最大連續(xù)和, 注意到異或運(yùn)算滿足結(jié)合律, 可以利用O(N^2)的時(shí)間枚舉每個(gè)區(qū)間. 但是這題范圍很大, 第6個(gè)點(diǎn)就TLE了.

            8.21


            charrec[DP + 統(tǒng)計(jì) + 記錄方案], 2.5h
            注意到題目對于最優(yōu)解的定義是損壞數(shù)據(jù)最少, 因而可以考慮DP.
            f[i] = min{f[i + 19] + C[i][19], f[i + 20] + C[i][20], f[i + 21] + C[i][21]}
            prev[i] = i + 19\20\21
            prevk[i] = K(C[i][_]對應(yīng)的字符)
            f[i]表示從第i行到第n行的最少損壞(不同位數(shù)). C[i][j]表示從第i行開始連續(xù)匹配j行的最小損壞(不同位數(shù)), 這里需要返回所對應(yīng)的字符, 實(shí)現(xiàn)時(shí)可以利用記憶化.
            對于f數(shù)組, (n - 19, n]需要初始化為+∞
            *可以利用d[i][j][k]表示第i個(gè)字符第j行和輸入數(shù)據(jù)第k行不同位數(shù)
            *需要注意數(shù)組大小, 以及題目中寫出的font.in和給出的font.in不同.

            picture[離散化+掃描線? / 離散化+線段樹 / 離散化], 1h
            1.無需離散化, 直接染色, 可以過8組數(shù)據(jù). -> But, 第7組莫名奇妙的掛了.
            [統(tǒng)計(jì)] 對于兩線段交點(diǎn), (G[i-1][j]^G[i+1][j]) && (G[i][j-1]^G[i][j+1])(即(i,j)左右\上下相鄰點(diǎn)顏色不同).
              對于一般點(diǎn), 水平方向上, 可以(G[i][j-1]^G[i][j+1]) && G[i-1][j] && G[i+1][j]. 豎直方向同理.
            2.掃描線 + 離散化 by BYVoid
            對于水平和豎直方向分別處理, 下面僅討論水平情況, 豎直同理.
            (1)對于每個(gè)矩形, 將其在水平方向上的邊按照縱坐標(biāo)的大小, 分為始邊和終邊.
            (2)按照縱坐標(biāo)升序掃描, 相同情況下始邊優(yōu)先(因?yàn)檫呏睾系臅r(shí)不算入周長). -> 快排即可
            (3)如果遇到始邊, ++ level[i]; 如果遇到終邊, -- level[i]; 如果出現(xiàn)level[i]從0到1的情況, ++ ans; 從1到0的情況相同, 不必考慮.
            -> 對于這一題直接掃描每個(gè)點(diǎn)即可, 如果數(shù)據(jù)范圍進(jìn)一步擴(kuò)大的話, 不妨使用線段切割.
            答案即為ans*2;
            *很像KOI10 Day2的某題, 當(dāng)時(shí)貌似我直接模擬, 然后數(shù)組爆了. 其實(shí)用sizeof算一下內(nèi)存即可.
            *突然發(fā)現(xiàn)神牛的構(gòu)造能力都很強(qiáng). 比如說BYVoid的做法, 個(gè)人以為最重要的是level數(shù)組的構(gòu)造.
            *如果自己寫計(jì)時(shí)函數(shù)并提交的話, 會(huì)發(fā)現(xiàn)USACO函數(shù)顯示的時(shí)間比USACO給出的時(shí)間少得多, 原因不知.
            *很奇葩的是, 以前一直用PROG, 然后USACO這次突然提示使用PROB -> 什么狀況

            twofive[Contor展開], ?h, 全仿std.
            1.暴搜 -> 理論6組, 實(shí)際4組 -_-
            2.類似kimbits, 可以使用康托展開(比較直觀的解說參見白書第10章).
            關(guān)鍵在于對于一個(gè)給定的串, 如何知道小于其前n位的串的方案數(shù). 定義f[a][b][c][d][e]表示方案數(shù). 對于每個(gè)字母ch, 如用過, 那么繼續(xù)ch+1. 否則枚舉已填位后所有位, 累計(jì)方案值.
            (數(shù)學(xué)描述)
            若ch未被使用, f[a][b][c][d][e] = f[a+1][b][c][d][e] + f[a][b+1][c][d][e] + f[a][b][c+1][d][e] + f[a][b][c][d+1][e] + f[a][b][c][d][e+1];
            初始化f[5][5][5][5][5] = 1.
            *[數(shù)組開小]
              > Run 1: Execution error: Your program had this runtime error:
                    Illegal file open (/dev/tty). The program ran for 0.000 CPU
                    seconds before the error.

            rectbarn[DP], 1.5h
            1.暴力, O(R^2*C^2*P), 可以過3個(gè)點(diǎn)
            2.參考WC03王知昆論文, 非常好理解
            懸線:上端點(diǎn)覆蓋了一個(gè)障礙點(diǎn)或達(dá)到整個(gè)矩形上端的有效豎線. 顯然對于每個(gè)懸線擴(kuò)展得到矩形一定包含答案. 我們可以利用O(RC)的時(shí)間得到所有懸線, 因而問題的關(guān)鍵在于利用O(1)的時(shí)間處理懸線. 這里可以使用DP.
            H[i][j] = H[i-1][j] + 1   (G[i][j]未損壞)
                0      (G[i][j]損壞)
            L[i][j] = min{l[j], L[i-1][j]} (G[i][j]未損壞)
                ∞      (G[i][j]未損壞)
            R[i][j] = min{r[j], R[i-1][j]} (G[i][j]未損壞)
                ∞      (G[i][j]未損壞)
            max{H[i][j]*(L[i][j] + R[i][j] - 1)}即為答案
            *北極天南星 和 論文 似乎都有一個(gè)地方把 min 打成了 max.
            *i和j不能隨意交換, 需要注意所對應(yīng)的下標(biāo)范圍.(#3 WA)

            vans[DP / SCDP], 1h
            奇葩的遞推式, f[n] = 2*(f[n-1] + f[n-2] - f[n-3]) + f[n-4] (n >= 5)
            初始化, f[1] = 0, f[2] = 2, f[3] = 4, f[4] = 5; f[50]之后需要高精度.
            *推導(dǎo)方法待研究.
            *求哈密頓回路個(gè)數(shù), 可以使用基于連通性的SC.

            cowxor[枚舉 + 優(yōu)化], 1h, 全仿std

            posted @ 2011-08-23 12:17 Climber.pI 閱讀(229) | 評論 (0)編輯 收藏

            寫在USACO通關(guān)之后

            大概在暑假之前, 我從來沒有想過能在暑假刷完Training.

            去年初賽后, 刷了幾道Contest Bronze的水題, 想要重啟Training, 但是在寫了一道完全背包之后, 水平所限, 無可奈何的放棄了.

            從高一開學(xué), 到NOIp后, 只寫了38k的程序. 今年5月, 寫了24k. 當(dāng)時(shí)的狀態(tài), 找不著北, 還要面對文化課的挑戰(zhàn). 而當(dāng)時(shí)的計(jì)劃又比較凌亂, 不管是訓(xùn)練還是比賽. 按照我當(dāng)時(shí)的能力, 應(yīng)該在9月初開始, 一直到11月一直寫DP. 期間可以穿插一些圖論和搜索的復(fù)習(xí), 11月可以學(xué)會(huì)寫一些簡單的暴搜(這個(gè)當(dāng)時(shí)做到了), 背一下裸的圖論代碼(當(dāng)時(shí)也做到了, 但是沒有上機(jī), 應(yīng)該找裸的算法題不斷提交默寫代碼). 不過確定校內(nèi)上機(jī)環(huán)境已然是開學(xué)第三周了, 還有軍訓(xùn)一周. 時(shí)間本不多, 加上中考的失落, 以及高一的迷茫.

            NOIp后曾一度拿到lrj老師推薦的題目, 大概是兩次吧. 不過UVa太猥了, 只有AC與否, 而且輸出格式紛繁, 實(shí)在是初學(xué)者的噩夢. 當(dāng)時(shí)水平有限, 或者說更確切的是自信有限. 不相信自己寫得出這樣的題目. 首先要相信自己能寫某一題, 然后就會(huì)寫了. 后面無可奈何的不了了之. 有點(diǎn)印象的僅僅是一道樹(模擬), 和spfa記錄方案.

            寒假面對實(shí)現(xiàn)能力痛定思痛, 重寫Chapter3. 大概一直到3月份才完成, 除了msquare和comelot. 同時(shí)一直寫在線的Contest, March終于進(jìn)了Silver, 而且寫的也不錯(cuò). 三個(gè)月寫了120k的代碼, 效果不錯(cuò), 之后就是歷時(shí)一個(gè)余月的”迎大運(yùn)”斷網(wǎng)活動(dòng). 應(yīng)該說這三個(gè)月實(shí)現(xiàn)能力有了初步提升.

            4月份幾乎一個(gè)月耗在了Chapter4上, 可是僅僅A了兩道最大流和一道最小環(huán). 嘗試了幾道題, 但是無果而終. 寫了幾種msquare, 這應(yīng)該是第二次研究Contor展開. 這個(gè)月網(wǎng)絡(luò)完全癱瘓, 第一周還腹痛如絞. 進(jìn)度極慢.

            5月初面對段考的結(jié)束, 以及4月份的奇慢進(jìn)度, 和dy學(xué)長談了幾乎一晚上. 之后就按照學(xué)長建議開始寫DP, 從tyvj開始. 一開始面對LIS和背包很輕松的解決了, 但是其他類型壓力很大, 經(jīng)常卡幾天然后某一天突然A兩三題. 之后學(xué)了一些東西, 看了jec推薦的動(dòng)歸八講 和 一套網(wǎng)上的題解. 而后得到了Ylen的建議, 開始考慮看題解和思考的平衡點(diǎn). 期間還準(zhǔn)備了LGOI的初賽, 結(jié)果較挫, 題目比較莫名其妙(完善最后一題), 大概前五吧. 重做去年初賽, 復(fù)習(xí)了空間向量, 突然發(fā)現(xiàn)去年第四題理解錯(cuò)題意, 其實(shí)就是一個(gè)查表找最小字典序. 去年卻認(rèn)為必須模擬, 還畫了二三十幅圖. 

            5月份的收獲主要是方向性的, DP和題解, 去年的思維誤區(qū). 盡管5月份訂的目標(biāo)是50道, 但是期末考試前大概只寫了20道, 應(yīng)該還是盲目思考太多. 思考和學(xué)習(xí)之間需要一個(gè)平衡點(diǎn), 隨著時(shí)間的推移, 會(huì)越來越偏向思考. 但是過早的傾向于思考會(huì)加大時(shí)間成本.

            6月份又開始準(zhǔn)備段考, 盡管結(jié)果很挫. LGOI的復(fù)賽正好和上課時(shí)間沖突了, 也沒心情去, 不了了之. 當(dāng)時(shí)的能力大概會(huì)300的算法, 不知道實(shí)現(xiàn)如何. 現(xiàn)在會(huì)400的算法, 不妨一試. 6月份的記憶似乎就剩下糾結(jié)前面某安保負(fù)責(zé)人的網(wǎng)線 和 生物王后雄了. 很難得的AK了王后雄前四章.

            暑假頹了半個(gè)月, 看小說, 看電視劇, 看電影, 準(zhǔn)備訂精華的課, 稍微動(dòng)了動(dòng)作業(yè).

            半個(gè)月開始正式訓(xùn)練, A題速度快了很多. 也學(xué)了很多東西, 比如樹形DP(目前只會(huì)兒子兄弟表示法), 同時(shí)鑒于tyvj的難度, 開始注意一題多解. 大概10天之后開始寫朱全民的<動(dòng)態(tài)規(guī)劃典型例題>, 寫了22題, 除了兩道SC. 大概總共用了3周時(shí)間完成上述工作, 52k代碼. 進(jìn)一步鞏固了樹形DP, 開始接觸SC. 信心大增.

            于是在個(gè)人膨脹的大背景下, Training被重新提上日程. 用了兩天的時(shí)間學(xué)習(xí)和復(fù)習(xí)暴搜, 重寫了n皇后問題(位運(yùn)算無能). 用了一周左右的時(shí)間寫完了Chapter4, 參考了一些題解, 除了fence8沒怎么參考別人的AC程序. 因?yàn)槿胧中耹aptop的緣故, 停兩天, 然后開始Chapter5, 學(xué)習(xí)凸包, 在window卡了半天. 第二天發(fā)現(xiàn)實(shí)現(xiàn)非常之簡單, 完全是去年寫矩形切割留下的心理陰影, 主程序才10line, Tarjan都要20line. 之后最惡心的題目應(yīng)該是twofive, 完全的實(shí)現(xiàn)無能, 照著標(biāo)程打了一遍才部分理解. Chapter6的題目幾乎都會(huì)寫暴力, 但是AC算法確實(shí)想不到, 而且居然涉及到多篇WC論文. 不管怎么樣, 總算過了. 實(shí)現(xiàn)能力越來越強(qiáng), 只要明白了算法, 可以在3h內(nèi)調(diào)出95%的程序. 但是由于題目難度, 很多題目做不到一題多解. 這半個(gè)月可能是搞OI以來最充實(shí)的半個(gè)月, 寫了87k的代碼.

            如果日后準(zhǔn)備KOI甚至更進(jìn)一步的話, 不妨重寫一遍Training后面的題目. 不同的是注重高級數(shù)據(jù)結(jié)構(gòu). 這次比較注重實(shí)現(xiàn)能力\調(diào)試能力和暴搜的訓(xùn)練, 較為輕視高級數(shù)據(jù)結(jié)構(gòu)和高級算法(比如兩道最小割都被無視了).

            這一年以來, 最重要的轉(zhuǎn)折點(diǎn)應(yīng)該是5月, 其次是1月, 然后是7月. 從5月開始, 量變逐漸產(chǎn)生質(zhì)變.

            接下來的任務(wù)是NOIp 2011, 目標(biāo)應(yīng)該是300左右, 雖然大部分年份的題目估計(jì)在3h內(nèi)單題AC. 但是考慮到整體時(shí)間, 應(yīng)該做到45min內(nèi)出第一題(水題情況), 并且讀完全卷, 制定計(jì)劃. 后三題按照難度大致完成兩題, 必須完成每題的暴力部分, 然后寫對拍.

            知識(shí)盲點(diǎn)還是有一些, 比如Contor展開, Hash, KMP, 最短路算法普遍很陌生, 并查集的應(yīng)用, 雙向廣搜, Tarjan等. 如果時(shí)間更多的話, 還有各種數(shù)論和遞推, 線段樹, 樹狀數(shù)組, 最大流. 實(shí)現(xiàn)盲點(diǎn)主要是對拍和暴力, 也許應(yīng)該先寫暴力, 然后寫AC算法(或者更強(qiáng)的部分算法), 寫makedata, 對拍. 寫暴力和makedata的時(shí)間應(yīng)該可以控制在10min內(nèi), 要多訓(xùn)練.

            題目的話, 歷年題目還有很多沒寫, POJ的DP分類, 各種模擬賽, Ural. 9月份以前兩者為主, 主要是練習(xí)算法, 增強(qiáng)熟練程度, 寫一些有難度的算法題. 明天先寫完Training最后兩題的題解, 然后復(fù)習(xí)一下Tarjan. 剩下幾天以整理暑假題目為主, 每天大概A1~2道題, 從LGOI和歷年開始. 至少在NOIp范圍內(nèi), 沒什么題目不能做.

            和一年前相比, 我更多的知道了我應(yīng)該做什么, 或者說, 更相信自己能做什么. 這應(yīng)該是一年來最大的突破.


            posted @ 2011-08-22 21:07 Climber.pI 閱讀(775) | 評論 (0)編輯 收藏

            Problem List (8.6 ~ 8.12)

            8.6

            poj 1731[全排列生成]

            參照白書上的做法, 關(guān)鍵在于
            (1)遞歸的邊界條件cur == n
            (2)遞歸調(diào)用的條件c1(在生成序列中出現(xiàn)次數(shù)) < c2(在原序列中出現(xiàn)次數(shù))
            (3)!i || P[i-1] != P[i]判重
            *需要注意, qsort可以直接對char排序

             

            RQNOJ四周年模擬賽 -> 據(jù)說是NOIp難度 -> 審題壓力很大
            [七顆果子]給出一個(gè)數(shù)開七次方
            30%的做法是直接開七次方
            AC算法, 注意到輸入不超過777位, 所以答案不超過[lg(10^(777/7))]+1 = 112位, 二分次數(shù)不超過log{2}{10^112} = 372.很明顯對于每一個(gè)輸入我們可以得到答案的位數(shù), 先利用位數(shù)確定范圍, 然后壓位高精乘.
            [七夕星夜]
            此題無思路..只會(huì)模擬. 猜測標(biāo)準(zhǔn)算法是DP+優(yōu)化
            [七色彩虹]
            將起點(diǎn)和終點(diǎn)各看做一朵云彩, 題目可以看作規(guī)定起點(diǎn)和終點(diǎn)的DAG最長路問題. 方程f(i, j) = min(f(k, j-1) + w(i, k)), 時(shí)間復(fù)雜度是O(N^7).由于每個(gè)點(diǎn)經(jīng)過不止一次, 不能利用vis.想不到什么優(yōu)化.
            [七夕的禮物]
            模擬或者利用公式[usaco friday涉及的蔡勒公式]
            [估計(jì)]理論得分190, 實(shí)際上120左右, 還不一定調(diào)的出來. 去年做的話, 應(yīng)該能90左右.


            8.7

            checker[DFS]

            思路和昨天的生成全排列如出一轍, 可行性剪枝都在擴(kuò)展節(jié)點(diǎn)的時(shí)候, 不同的是此題利用vis避免了循環(huán)檢查.
            *把vis數(shù)組利用位運(yùn)算實(shí)現(xiàn), 速度提升不大, 從0.73s到0.7s而已.
            *M67給出的位運(yùn)算做法只需要0.135s, 測試后發(fā)現(xiàn)兩程序遞歸次數(shù)一樣. 主要差別應(yīng)該是在循環(huán)擴(kuò)展節(jié)點(diǎn).
            *vis下標(biāo)打反一次, 沒有看對稱性剪枝.
            *發(fā)現(xiàn)一個(gè)驚人事實(shí), USACO服務(wù)器計(jì)算能力加強(qiáng)了, NOCOW上據(jù)說0.9X的程序, 現(xiàn)在提交0.6X.

             

            poj 1049[DFS], 1h, 3WA
            直接套用生成全排列, 不同的是遞歸邊界條件不是l而是c, 擴(kuò)展節(jié)點(diǎn)注意滿足A[i-1] < A[i]
            *萬般無奈找std對拍, 復(fù)習(xí)了隨機(jī)數(shù)和bat的寫法, 再次提示, 注意靜態(tài)查錯(cuò)!!!


            fence8
            全排列生成+可行性剪枝, 時(shí)間復(fù)雜度O(K!), 只過了一個(gè)測試點(diǎn) -_-


            poj 3050[DFS], 50min
            學(xué)習(xí)DFS-ID, 突然發(fā)現(xiàn)我昨天寫的事實(shí)上就是DFS-ID. 不同的是, DFS-ID將深度逐漸遞增, 進(jìn)行多次搜索. 也就是說會(huì)存在一些冗余, 但是鑒于解答樹的節(jié)點(diǎn)主要集中在最后兩層, 所以前面的狀態(tài)量并不大. 事實(shí)上DFS-ID結(jié)合了BFS處理距離節(jié)點(diǎn)最近的問題, 以及DFS的空間復(fù)雜度優(yōu)勢.
            *調(diào)試了20min, 原因是因?yàn)閷顟B(tài)編碼的一個(gè)循環(huán)寫錯(cuò)了. -> 如果涉及多組易混變量的話, 一定要重點(diǎn)檢查.
            *Hash表的MaxState如何確定?
            [Training關(guān)于BFS\DFS\DFS-ID的介紹]http://www.oiers.cn/usaco%20training/11-401.asp.htm


            8.8


            fence8[高仿dd_engi牛的程序]
            枚舉每一個(gè)board可以切成那些rail, 分析各種剪枝的動(dòng)機(jī).
            優(yōu)化:
            1.排序后計(jì)算Σrail[1..i]>Σboard[1..N]的R=i的最小值 => 縮小R的可能性
            2.二分[如何處理邊界???] => 減少DFS-ID的枚舉量
            *關(guān)于邊界處理的動(dòng)機(jī) by gXX
            因?yàn)槲ㄒ坏膯栴}就是出現(xiàn)在[i, i + 1]這種區(qū)間, 你總是要調(diào)整mider的取法, 使得每次至少能夠刪掉一個(gè)元素。
            (1)如果mider成功調(diào)整為[left, mider]否則是[mider + 1, right]
            那么你需要寫一個(gè)mider = (left + right + 1) / 2;
            (2)如果mider成功調(diào)整為[mider, right]否則是[left, mider - 1]
            那你就要寫mider = (left + right) / 2
            (3)在區(qū)間長度小于2的時(shí)候進(jìn)行特判
            3. rail[i] == rail[i-1] -> 這一個(gè)能切出來, 下一個(gè)直接試能不能切一個(gè)同樣的
            4. board[i] == board[i-1] -> 相等的情況下, 這個(gè)能切出來, 下一個(gè)顯然也能切出來
            [關(guān)于剪枝3和4]
            如果有兩個(gè)欄桿的長度相同,那么這兩個(gè)欄桿從哪兩塊木板或者從一塊木板中切出對最終結(jié)果是沒有影響的,所以在遍歷木板的時(shí)候,可以按照木板的順序進(jìn)行切割。比如規(guī)定一種次序,編號靠前的木板優(yōu)先切割相同欄桿的第一個(gè),以此類推,那么當(dāng)rail[i]==rail[i+1]時(shí),現(xiàn)在用第k塊木板切出欄桿i,則欄桿i+1就從第k塊或者更后面的木板進(jìn)行切割,而不必再從頭開始,因?yàn)閕+1在i前面的情況已經(jīng)搜索過了,其實(shí)將i+1與i的位置互換一下就是了;同理,如果兩個(gè)木板相同,那么也規(guī)定靠前的優(yōu)先切割欄桿;
            [剪枝動(dòng)機(jī)] by wh
            這個(gè)剪枝主要是充分利用數(shù)據(jù)性質(zhì)進(jìn)行不等式控制,和生日蛋糕有點(diǎn)類似之處。所以說對于“切割”類的搜索題,通常他的“剩余部分”往往隱含著一些限制,可以作為剪枝的突破口
            另外這個(gè)剪枝有個(gè)使用前提,就是要先轉(zhuǎn)化成判定性問題,因此這也是我們必須id-dfs的原因


            rqnoj 350[查找第k大]
            這題對于類似快排來說數(shù)據(jù)比較強(qiáng), Hoare劃分法的時(shí)間常數(shù)比Lomuto劃分法時(shí)間常數(shù)少一些, 平均復(fù)雜度O(N), 最差的話O(N^2). 真正意義上的O(N)算法似乎是非常麻煩的分治. 在本題中復(fù)雜度為O(MN). 使用平衡樹的話可以做到O(MlogN).
            *需要注意的是, 算法中存在swap操作, 故而如果求區(qū)間最值的話需要重新賦值
            *Hoare的話實(shí)際上就是左右開弓..
            *Lomuto的話實(shí)際上就是折騰序列最后一個(gè)數(shù), 所以會(huì)多了很多不必要的swap
            *這個(gè)隨手寫的例子不錯(cuò)
            7 7
            5 1 3 2 6 8 7


            tyvj 1001[查找第k大/小 + 素?cái)?shù)判斷]
            練習(xí)Lomuto劃分法查找第k大
            *查找第k大算法O(N)較直接排序O(NlogN)的差別不大, 而且更大的數(shù)據(jù)范圍需要更高級的數(shù)據(jù)結(jié)構(gòu), 總的來說用處不大.


            buylow[LIS+高精], 3h+1.5h.
            方程考慮不周1h, 調(diào)試高精2h, 理解算法1h.
            對于第二問, 注意到對于f[i] = f[j] + 1(j < i), 存在A[j] <= A[i](因?yàn)轭}目要求最長不下降子序列). 因而可以記錄prev[i]表示f[i]的上一個(gè)f[j]的值, 注意f[i] > f[j]+1和f[i] == f[j+1]都要更新.然后會(huì)在第5個(gè)點(diǎn)掛掉.
            即使是相同的A[j], 它們所對應(yīng)的g[j]不同, 按照題意應(yīng)取最大的. 故而prev[i]需要記錄上一個(gè)j的下標(biāo).
            f[i] = max(f[j]+1);
            prev[i] = j(f[i] >= f[j]+1)
            g[i] = Σmax(g[prev[i]]) (每個(gè)不同的A[j]對應(yīng)的最大g[j]) -> 這里需要不斷更新, 因而需要高精減
            為了簡化, 在序列末尾增加元素0, 故而f[n], g[n]即為答案.
            *對于方程2, 可以用next[i]記錄與A[i]相同且最近的值的下標(biāo), 計(jì)算方案時(shí)若next[i] && next[i]<i直接跳過. by BYVoid
            ->同樣的A[i], 最后一個(gè)的g[i]最大. 假設(shè)A[j]==A[i], 存在g[j]<=g[i], 若區(qū)間(j, i)不存在A[k]>A[i]等號不成立.
            *對于雙目運(yùn)算符, 函數(shù)()后要加const, 函數(shù)參數(shù)要加const和&, 注意利用初始化結(jié)合題目要求.
            *第一版程序+=函數(shù)出現(xiàn)前導(dǎo)零
            *對于每一道相似的題目, 要著重思考不同點(diǎn), 在紙上得到正確的方程. 否則會(huì)在調(diào)試過程中浪費(fèi)兩倍的時(shí)間.
            *靜態(tài)查錯(cuò)可以避免浪費(fèi)更多的調(diào)試時(shí)間, 要分析每個(gè)函數(shù)每條語句的動(dòng)機(jī), 以及實(shí)現(xiàn)情況. 不要盲目調(diào)數(shù)據(jù).


            8.9


            fence6[DFS], 2h, 數(shù)據(jù)弱
            *這題充分暴露了對題意分析不明, 貿(mào)然上手的后果. 此題應(yīng)在40min內(nèi)解決, 20min左右設(shè)計(jì)DFS, 剩余時(shí)間調(diào)試.
            (1)標(biāo)號. 利用map數(shù)組存儲(chǔ)標(biāo)號, 然后將下面的讀入下標(biāo)全部用map映射. -> 讀題時(shí)應(yīng)該完成
            (2)DFS. 枚舉每個(gè)點(diǎn), 向右邊DFS, 除了出發(fā)點(diǎn)不能再次加入. 但是題目中給出的left和right是亂序的, 也就是說必須記錄prev, 然后從不含prev的一側(cè)繼續(xù)遍歷. 所以DFS的狀態(tài)為(起始邊, 正在遍歷邊, 上次遍歷邊, 已遍歷邊權(quán)), 利用循環(huán)檢查確定遍歷方向.
            *以前寫Chapter2時(shí)就是這樣, 題目在自己的能力范圍內(nèi), 但是不注意題目的分析, 浪費(fèi)大量時(shí)間.


            cryptcow[算法1, 實(shí)現(xiàn)無能], 8h
            讀入原串后記錄C\O\W的個(gè)數(shù)及位置, 個(gè)數(shù)不同則直接無解, 同時(shí)處理前綴和后綴(第一個(gè)C之前的和最后一個(gè)W之后的),然后深搜.
            深搜過程(層數(shù)直接通過(原串-目標(biāo)串)/3確定)中出現(xiàn)的新字符串用map記錄下標(biāo), memcpy完成下標(biāo)的復(fù)制和恢復(fù), 利用vis判重(對于每個(gè)C\O\W).
            其中比較麻煩的是C\O\W在變換后位置的更新和恢復(fù), 花費(fèi)了很多時(shí)間調(diào)試. 就算在紙上先算好下標(biāo)的變換值, 還是很容易因?yàn)槎鄠€(gè)函數(shù)同時(shí)改變導(dǎo)致錯(cuò)誤. 第二天上午最終過了3個(gè)數(shù)據(jù)點(diǎn), 其余提示崩潰, 調(diào)試無能.
            *了解一些細(xì)節(jié):std關(guān)鍵字會(huì)引起沖突; memcpy(,,字節(jié)數(shù)), 一般為sizeof(類型)*數(shù)量
            *比較奇怪的是利用fgets讀入第一個(gè)數(shù)據(jù)會(huì)自動(dòng)加回車.


            8.10

            ctyptcow[算法2], 5h
            通過學(xué)習(xí)<string>的一些特性(《C++ Primer Plus》記錄的很詳細(xì)), 50min寫完了不加任何優(yōu)化的爆搜, 過了5個(gè)點(diǎn).
            1.得到s串的子串[i,j]: string newname(&s[i], &s[j]) -> 類似這樣的函數(shù)還有別的一些神奇的寫法
            2.通過+\+=完成連接; .size()/.length()計(jì)算長度
            3.getline(file, value) -> 有value的長度限制讀入長度, 不必顯式制定.
            接下來是實(shí)現(xiàn)各種優(yōu)化:
            1.改變搜索順序, 先順序搜O, 然后順序搜C, 最后逆序搜W(逐層if)
            2.判斷變換后的串COW間的子串是否為原串的子串, 可以記錄原串每種字符出現(xiàn)的位置, 不是原串子串的話, 剪枝
            3.判斷變換后的串第一個(gè)C, 最后一個(gè)W的位置, 若C>W或從兩端沒有找到C/W但是找到O, 剪枝
            4.利用ELF Hash. 嚴(yán)格意義上這步算騙分, 選取質(zhì)數(shù)131071時(shí)恰好沒有沖突. 但是嚴(yán)格意義上的Hash需要判重
            5.找到第一個(gè)C和最后一個(gè)W, 確定DFS字符范圍 -> 這個(gè)用了反而TLE
            *對于涉及到數(shù)組的問題, 不一定要按照原來改變 -> 恢復(fù)的模式, 應(yīng)該設(shè)法避免“恢復(fù)”過程.
            *關(guān)于Hash, 參見WC2007李羽修《Hash函數(shù)的設(shè)計(jì)優(yōu)化》, 很驚悚的發(fā)現(xiàn)我居然用直接取余A了.
            *最后一個(gè)測試點(diǎn)卡著過的.


            8.11


            job[貪心(對稱性) + 二分], 1h
            首先要注意到這題是多機(jī)器并行工作, 所以不能使用DP, 可以貪心. 事實(shí)上如果從1到max{A[i]}*n逐個(gè)枚舉t, 就可以得到最小的t. 這提示我們可以使用二分, 判定函數(shù)為Σt/A[i](1<=i<=n).
            對于兩種操作A、B, 要分別計(jì)算最短時(shí)間和方案(要保證A[]\B[]序列升序), 然后利用對稱性找最大值.
            *計(jì)算方案利用二重循環(huán), 1..t為外層i, 1..na\nb為內(nèi)層j, 未生產(chǎn)工件數(shù)為rest, 如果rest>0&&i|j, 那么ta\tb[n-(--rest)] = i;
            *對于二分, 目前掌握兩種寫法. 一是lrj白書l>=r;check(m);l=m+1;r=m, 二是dd_engi在fence8中的l+1=r;check(m-1);l=n;r=m;


            stall4[二分圖最大匹配 -> 匈牙利算法]
            [二分圖最大匹配問題匈牙利算法]http://www.matrix67.com/blog/archives/39
            [匈牙利算法]http://www.byvoid.com/blog/hungary/
            [二分圖最大匹配的K?nig定理及其證明]http://www.matrix67.com/blog/archives/116
            第三項(xiàng)和這題關(guān)系不大.
            [匈牙利算法] by M67
            從二分圖中找出一條路徑來,讓路徑的起點(diǎn)和終點(diǎn)都是還沒有匹配過的點(diǎn),并且路徑經(jīng)過的連線是一條沒被匹配、一條已經(jīng)匹配過,再下一條又沒匹配這樣交替地出現(xiàn)。找到這樣的路徑后,顯然路徑里沒被匹配的連線比已經(jīng)匹配了的連線多一條,于是修改匹配圖,把路徑里所有匹配過的連線去掉匹配關(guān)系,把沒有匹配的連線變成匹配的,這樣匹配數(shù)就比原來多1個(gè)。不斷執(zhí)行上述操作,直到找不到這樣的路徑為止。
            *可以從每個(gè)點(diǎn)開始找增廣路, 最初的覆蓋是空集, 第一個(gè)點(diǎn)過后就有了一條邊, 之后邊數(shù)會(huì)逐漸增多, 直到不存在交錯(cuò)路.
            *似乎這題應(yīng)該是無向圖, 但是寫有向圖也不影響結(jié)果.


            tyvj 1035[二分圖最大匹配 -> 棋盤覆蓋], 1h
            對棋盤進(jìn)行染色, 標(biāo)記不能通過的點(diǎn), 然后對于每個(gè)點(diǎn)(x,y), 分別和(x-1,y) (x,y-1) (x+1,y) (x,y+1)建立邊(另一個(gè)點(diǎn)必須可以通過). 這里可以把二維坐標(biāo)一維化, 之后這屆套用匈牙利算法即可.
            *注意輸入中的坐標(biāo)從1開始, 而實(shí)現(xiàn)中從0開始
            *注意擴(kuò)展邊的時(shí)候, 新點(diǎn)同樣可以訪問 -> 卡了30min


            poj 1422[二分圖最大匹配 -> 最小路徑覆蓋], 20min, 1Y
            [轉(zhuǎn)載]在一個(gè)有向圖中,路徑覆蓋就是在圖中找一些路徑,使之覆蓋了圖中的所有頂點(diǎn),且任何一個(gè)頂點(diǎn)有且只有一條路徑與之關(guān)聯(lián);(如果把這些路徑中的每條路徑從它的起始點(diǎn)走到它的終點(diǎn),那么恰好可以經(jīng)過圖中的每個(gè)頂點(diǎn)一次且僅一次)
            將圖中的每個(gè)點(diǎn)拆為出點(diǎn)和入點(diǎn), 將原來的邊轉(zhuǎn)化為出點(diǎn)和入點(diǎn)間的有向邊, 利用匈牙利算法可以得到最大匹配數(shù)p. 顯然二分圖中每個(gè)匹配的出點(diǎn)都存在后繼, 故而這些點(diǎn)不可能是DAG的重點(diǎn), 因而答案為n-p.
            [這個(gè)寫得比較好]http://www.cnblogs.com/jackiesteed/articles/2043934.html


            向gXX神牛請教如何對拍.


            cowcycle[DFS], 2h
            同時(shí)枚舉F-組合和R-組合, 數(shù)據(jù)較弱, 加上可行性剪枝就A了.
            1.搜索順序
            注意到題目要求答案字典序最小, 故而可以逆序枚舉避免對字典序的判斷.(也可以順序, 然后找一個(gè)比較強(qiáng)的條件, 在完成找到答案后退出, 效率估計(jì)逆序的幾倍.)
            2.狀態(tài)設(shè)置
            dfs(當(dāng)前F kf, 當(dāng)前R kr, 剩余F數(shù) nf, 剩余R數(shù) nr).
            3.終止條件
            nf = nr = 0 || kf + 1 < F1 || kr + 1 < R1.
            對于nf = nr = 0, 進(jìn)行可行性剪枝(判斷傳動(dòng)比率倍數(shù)) -> 注意這里是int
            4.狀態(tài)轉(zhuǎn)移
            非常麻煩, nf/nr為零的情況需要單獨(dú)處理, 4種轉(zhuǎn)移方式, 但是有8種情況.
            5.優(yōu)化
            1)考慮到生成的待排序序列與排序后很接近, 而且數(shù)據(jù)量極小, 于是用冒泡代替快排
            2)求平均值時(shí), 先累加, 最后除; 求方差時(shí)直接忽略除, 不影響結(jié)果
            這樣可以把最后一個(gè)點(diǎn)從1.9s優(yōu)化到0.6s, 很有效的控制常數(shù).
            *所有同時(shí)涉及double和int的語句, 必須進(jìn)行強(qiáng)制類型轉(zhuǎn)換
            *memcpy(ansF+1, f+1, sizeof(int)*F)必須這樣寫, 如果將第三部分寫作sizeof(f)或sizeof(f+1)導(dǎo)致錯(cuò)誤 -> 原因不明
            *對于這類比較復(fù)雜的搜索, 應(yīng)該現(xiàn)在紙上寫出大致模型, 并試圖找出一些問題. 直接寫程序很容易寫錯(cuò)變量名, 或者出現(xiàn)設(shè)計(jì)問題. 這樣應(yīng)該能夠大幅減少調(diào)試時(shí)間.


            8.12


            lgame[枚舉 + 優(yōu)化], 2h
            1.讀入目標(biāo)串并記錄分值.
            2.讀入字典, 如果字典中串的長度小于等于4, 且目標(biāo)串長度大于7, 記錄該串. 需要注意該串的每一個(gè)字母出現(xiàn)次數(shù)不應(yīng)超過目標(biāo)串出現(xiàn)字?jǐn)?shù).
            3.如果該串分?jǐn)?shù)大于等于目前記錄最大分?jǐn)?shù), 則更新答案. 比較奇怪的是這里memcpy直接用sizeof(dic[t])不影響結(jié)果, 可能是字符串的原因.
            4.對記錄子串進(jìn)行枚舉, 并更新答案. 這里如果利用字符數(shù)組的話, 要注意計(jì)算連接處的坐標(biāo)(不妨利用for, memcpy容易出錯(cuò))
            *對于字符串可以利用qsort間接排序, cmp函數(shù)先逐位比較, 然后比較長度.
            *注意到題目中每個(gè)單詞不超過7個(gè)字母, 但是輸出中可能包含空格! 如果內(nèi)存過小或不指定'\0'的話, 會(huì)繼續(xù)輸出后面的字符串.
            *對于這類寫代碼都需要0.5h的題目, 需要思考如何減少調(diào)試時(shí)間, 現(xiàn)在調(diào)試時(shí)間是思考算法和寫代碼時(shí)間的兩倍.

            posted @ 2011-08-18 12:31 Climber.pI 閱讀(253) | 評論 (0)編輯 收藏

            USACO Training 4.1.4 Cryptcowgraphy

            USER: Yupan Liu [liuyupa1]
            TASK: cryptcow
            LANG: C++
            
            Compiling...
            Compile: OK
            
            Executing...
               Test 1: TEST OK [0.000 secs, 3240 KB]
               Test 2: TEST OK [0.000 secs, 3240 KB]
               Test 3: TEST OK [0.000 secs, 3240 KB]
               Test 4: TEST OK [0.000 secs, 3240 KB]
               Test 5: TEST OK [0.000 secs, 3240 KB]
               Test 6: TEST OK [1.377 secs, 3240 KB]
               Test 7: TEST OK [0.054 secs, 3240 KB]
               Test 8: TEST OK [1.026 secs, 3240 KB]
               Test 9: TEST OK [1.782 secs, 3240 KB]
               Test 10: TEST OK [1.971 secs, 3240 KB]
            
            All tests OK.
            

            Your program ('cryptcow') produced all correct answers! This is your submission #37 for this problem. Congratulations!



            僅此記錄AC的喜悅.

            posted @ 2011-08-10 20:36 Climber.pI 閱讀(250) | 評論 (0)編輯 收藏

            Problem List (7.26 ~ 8.5)

            7.26

            最長公共子序列l(wèi)cs, O(N^2)
            f[i][j] = max{f[i-1][j], f[i][j-1], f[i-1][j-1]+1(if A_i==B_j)}
            初始化f[_][0] = f[0][_] = 0

            7.27

            編輯距離edit, O(N^2)
            f[i][j] = min(f[i][j-1] + 1, f[i-1][j] + 1, f[i-1][j-1] + !(A_i==A_j))
            初始化f[i][0] = f[0][i] = i
            *參考[這里]http://en.wikipedia.org/wiki/Levenshtein_distance
            *狀態(tài)轉(zhuǎn)移過程中, 充分不一定最優(yōu), 必要才是最優(yōu); 事實(shí)上邊界條件總有其具體意義
            *[相關(guān)]http://www.matrix67.com/blog/archives/333

            最短回文串palindrome[poj 1159], O(N^2)
            1.套用lcs, O(N^2), 60
            f[i][j] = max{f[i-1][j], f[i][j-1], f[i-1][j-1]+1(if A_i==B_j)}
            初始化f[_][0] = f[0][_] = 0, n - f[n][n]即為答案
            *利用滾動(dòng)數(shù)組優(yōu)化, 空間復(fù)雜度O(N), 80
            *關(guān)鍵語句k = 1 - k, 注意在內(nèi)層循環(huán)外
            2.套用edit, O(N^2), 30
            f[i][j] = min(f[i][j-1] + 1, f[i-1][j] + 1, f[i-1][j-1] + 2*!(A_i==A_j))、
            初始化f[i][0] = f[0][i] = i, f[n][n]/2即為答案
            3.O(N^2), 30
            f[i,j]表示將Ai..Aj變?yōu)榛匚拇淖钚〈鷥r(jià),則
            f[i][j] = f[i+1][j-1] (若Ai=Aj)
                min(f[i+1][j],f[i][j-1])+1 (若Ai<>Aj)
            4.利用位運(yùn)算優(yōu)化
            http://www.csse.monash.edu.au/~lloyd/tildeStrings/Alignment/86.IPL.html

            硬幣找零coin[完全背包], O(N^2)
            f[j] = min(f[j], f[j-c[i]]+1)
            初始化f[0] = 0, f[1..T] = INT_MAX
            *注意下標(biāo)非零 和 INT_MAX的溢出

            7.28

            導(dǎo)彈攔截missile[LIS + 二分], O(NlogN)
            (1)二分查找O(logn)
            f[i] = max(f[j] + 1) (j < i)
            d[i] = min(f[k]) (f[k] == i)
            易知d[i]單調(diào), 因而可以利用二分查找降低復(fù)雜度, i最大值即LIS長度為t, 那么
            i)  f[i-1] < k <= f[i] (1 <= i <= t)
            ii) 若k > 任意f[], 則f[t+1] = k;
            iii) 若!k, 則f[1] = k;
            *例子參見[這里]http://www.matrix67.com/blog/archives/112
            [代碼實(shí)現(xiàn)]
            //情況ii和iii需要單獨(dú)處理
            x = 1; y = t;
            while (x <= y){
             m = (x + y)/2;
             if (f[m-1] < k && k <= f[m]) break;//對于最長上升子序列和最長不下降子序列判定條件不明???
             //if (f[m-1] < k && k <= f[m]) return m;
             else if (k > f[m]) x = m + 1;
             else y = m - 1;
             //return x;
            }
            *利用注釋, 可以避免對情況ii的單獨(dú)處理LIS的方案, 記錄方案需要使用pre數(shù)組, 范例不知???
            *需要注意的是, f數(shù)組給出的并非是一個(gè)
            (2)最少鏈劃分 = 最長反鏈長度(關(guān)于偏序集, 參見《組合數(shù)學(xué)》P73)
            [Dilworth定理]令(X,≤)是一個(gè)有限偏序集,并令m是反鏈的最大的大小。則X可以被劃分成m個(gè)但不能再少的鏈。

            最長不下降子序列l(wèi)is[LIS + 二分], O(NlogN)
            對[1..k-1][k+1..n]兩個(gè)序列分別進(jìn)行一次LIS即可.
            *問題的關(guān)鍵之處在于第一次理解不徹底和浮躁, 以及對于困難程度的不合理估計(jì).

            7.29

            加分二叉樹tree[區(qū)間 + 記錄方案], O(N^3), 20min
            f[i][j] = max(f[i][k-1] * f[k+1][j] + A[k]) (i <= k <= j)
            初始化f[i][i] = A[i], f[i+1][i] = 1
            [記錄方案]pa[i][j] = k, 遞歸即可, [邊界]pa[i][j] == i 或者 j, 以及i == j的情況

            整數(shù)劃分separate[區(qū)間 + 記錄方案], O(N^3), 2h
            f[k][i]表示序列1..i分成k段的最大值
            f[k][i] = max(f[k-1][j-1] * A[j][i])
            pa[k][i] = j
            初始化f[1][_] = A[1][_], 其他f[][] = -1
            *注意等號情況同樣需要更新
            if (f[K][i] <= f[K-1][k-1] * A[k][i])
             f[K][i] = f[K-1][k-1] * A[k][i],
             pa[K][i] = k; //記錄方案
            *將[pa[k][i], i]加入答案, 遞歸[1, pa[k][i]-1], [邊界] k == 0
            *在Win下使用long long占位符為"%I64d", 在Linux下占位符為"%lld", 考試中利用<fstream>避開占位符問題

            凸多邊形的三角剖分division[區(qū)間]
            f[i][j] = max{f[i][k] + f[k][j] + w(i, j, k)} (i < k < j)
            初始化1<=i-j<=2的f只為0, 其他為-1
            *表達(dá)式中同時(shí)出現(xiàn)long long和int的話, 會(huì)自動(dòng)轉(zhuǎn)換為int
            *只過了6個(gè)點(diǎn), 原因不知 -> 數(shù)據(jù)錯(cuò)誤, 最后4個(gè)點(diǎn)output一樣
            *各種神牛們普遍指出沒有考慮i>j的情況 -> 怎么寫???

            機(jī)器分配machine[區(qū)間], O(N^3)
            f[i][j] = max(f[i-1][k] + A[i][j-k]) (0 <= k <= j)
            初始化f[][] = 0, f[i][j] = max(f[i][j], A[i][j])
            *注意讀題"第i個(gè)公司分配j臺(tái)機(jī)器的盈利", 不是分配第j臺(tái)機(jī)器的盈利

            裝箱問題box[分組背包], O(N^2), 30min
            f[i][j] = max{f[i-1][j], f[i-1][j-c[i][k]] + w[i][k]}
            初始化f[][] = 0
            *讀題時(shí)注意變量的對應(yīng)關(guān)系
            *注意本題中背包不一定要裝滿

            7.31

            最長前綴prefix[判斷性dp], O(kN), 70min
            f[i] |= f[i - len[j]] & check(i - len[j] + 1, j) (1 <= i,j <= n)
            初始化f[] = 0, check(x,y)表示主串[x,x+len[y]-1]和前綴y是否相同
            *弄錯(cuò)j和len[j], 注意方程的字母指代, 以及實(shí)現(xiàn)中的字符指針位置, 注意靜態(tài)查錯(cuò)[30min]
            *[8.4優(yōu)化]把check函數(shù)直接寫在循環(huán)中, 如果f[i] == 1直接break -> 依舊超時(shí)三個(gè)點(diǎn)
            *[8.5優(yōu)化]i的上限為min(n, ans + 20), 更新f[i]的時(shí)候記錄ans即可 -> AC
            8.1

            關(guān)鍵子工程project[DAG最長路], 70min
            f[i] = max(f[j] + w[i]) (G[j][i] == 1)
            初始化f[i] = w[i]
            記錄方案, 利用f[i] == w[i] + f[j] (G[j][i] == 1)
            *利用定義求拓?fù)渑判? 輸出方案可以利用隊(duì)列將遞歸轉(zhuǎn)化為迭代, 無解情況用flag標(biāo)記(inq數(shù)組表示是否在隊(duì)列中)
            *在紙上寫出關(guān)鍵部分的代碼, 兩倍行距(比如遞推或者記憶化函數(shù), 輸出方案的函數(shù))

            8.2

            三角蛋糕trigon[坐標(biāo)dp], 130min
            [做法1](需保留空格)
            f_[i][j]表示以(i, j)為頂點(diǎn)的Rt△的最大邊長
            對于倒三角形, 自右向左 f1[i][j] = min(f1[i+1][j], f1[i][j+1]) + 1
                自左向右 f2[i][j] = min(f2[i+1][j], f2[i][j-1]) + 1
            對于正三角形, 自右向左 f1[i][j] = min(f1[i-1][j], f1[i][j+1]) + 1
                自左向右 f2[i][j] = min(f2[i-1][j], f2[i][j-1]) + 1
            初始化, f[][] = 0(A[][] = '#'), f[][] = 1(A[][] = '-'); min(f1[i][j], f2[i][j])^2的最大值即為答案
            [做法2](不需保留空格)
            f[i][j]表示以(i, j)為頂點(diǎn)的△的最大高度
            對于倒三角形, f[i][j] = min(f[i-1][j], f[i-1][j+1], f[i-1][j+2]) + 1
            對于正三角形, f[i][j] = min(f[i+1][j], f[i+1][j-1], f[i+1][j-2]) + 1
            初始化, f[][] = 0(A[][] = '#'), f[][] = 1(A[][] = '-'); min(f[i][j])^2即為答案
            *輸入需保留空格, 卡了30min(排除ASCII為10或13的字符即可)
            *沒有考慮正方向, 大約2h時(shí)對照std發(fā)現(xiàn)
            *有兩個(gè)點(diǎn)數(shù)據(jù)錯(cuò)誤, 對照std后發(fā)現(xiàn)std僅當(dāng)橫坐標(biāo)為奇數(shù)是考慮倒三角形, 橫坐標(biāo)為偶數(shù)時(shí)考慮正三角形, 而題目中無此限制
            *學(xué)習(xí)利用批處理對拍的寫法
            @echo off
            :again
            gen
            trigon
            trigon_me
            fc trigon.out trigon_me.out > nul
            if not errorlevel 1 goto again

            選課course[樹形dp]
            [做法1]多叉轉(zhuǎn)二叉
            f[i][j]表示以i為根節(jié)點(diǎn)的樹中, 選擇j門課
            f[i][j] = max(f[i.r][j], f[i.l][k] + f[i.r][j-k-1] + i.v) (0<=k<j)
            初始化f[][] = 0
            *無法記錄方案 -> gXX表示比較困難
            [做法2]泛化物品
            ??? -> 想撞墻 -> 需要學(xué)習(xí)

            通向自由的鑰匙key[樹形dp], 150min, zoj 2280
            f[i][j]表示以i為根節(jié)點(diǎn)的數(shù), 花費(fèi)能量為j時(shí)可以拿到的最多的鑰匙數(shù)
            f[i][j] = max(f[i.r][j], f[i.l][k] + f[i.r][j-k-i.c] + i.v) (o<=k<=j-i.c)
            初始化f[][] = -1, 邊界處理f[i][j] = 0(i<=0 || j<0)
            *記錄各點(diǎn)鄰接矩陣, 利用dfs構(gòu)造樹(注意處理后取消鄰接), 并多叉轉(zhuǎn)二叉 -> 30min
            *對于f[i.r][j]不必在記憶化搜索函數(shù)中遍歷所有兄弟, 只遍歷最近的即可
            *注意讀題, 出發(fā)點(diǎn)為1, i.c和i.v非負(fù) -> 1.5min
            *注意靜態(tài)查錯(cuò), 如記憶化搜索中dp(i, j)打成f(i, j)的情況
            *覺得比較暈的時(shí)候等一下再調(diào)題, 可以先干點(diǎn)別的, 這樣可以減少時(shí)間的浪費(fèi)

            警衛(wèi)安排security[樹形dp], 100min
            [狀態(tài)]
            f[i][0]表示以i為根節(jié)點(diǎn), 并在i安排警衛(wèi)的最小花費(fèi)
            f[i][1]表示以i為根節(jié)點(diǎn), i的父節(jié)點(diǎn)已安排警衛(wèi)的最小花費(fèi)
            f[i][2]表示以i為根節(jié)點(diǎn), i的子節(jié)點(diǎn)已安排警衛(wèi)的最小花費(fèi)
            [方程]
            f[i][0] = Σmin(f[i.son][0], f[i.son][1], f[i.son][2]) + i.v
            f[i][1] = Σmin{f[i.som][0], f[i.son][2]} (i不是樹的根節(jié)點(diǎn))
            f[i][2] = min{Σmin{f[i.son][0], f[i.son][2]}(i.son != k) + f[k = i.son][0]}
            [初始化]
            對于葉節(jié)點(diǎn), f[i][0] = i.v, f[i][1] = 0, f[i][2] = i.v
            對于其他值, f[][] = -1
            *對于根節(jié)點(diǎn)的尋找, 利用prev[i]記錄i的前驅(qū), 若!prev[i], 則i為樹根
            *結(jié)合批處理和makedata以及小范圍暴力程序, 可以有效地避免各種錯(cuò)誤及極端情況 -> 需要學(xué)習(xí)搜索
            *對于這類題目, 思考的關(guān)鍵在于分類寫出方程, 并注意方程的邊界條件(類似:tyvj 沒有上司的舞會(huì))
            *對于樹形dp, 存在兩種類型; 一種是對于加權(quán)路徑長度限制, 另一種則是求加權(quán)最值

            8.4

            青蛙的煩惱frog[區(qū)間dp]
            初看是最小生成樹問題, 但是此題有幾個(gè)特別的性質(zhì):
            1.以1號荷葉為起點(diǎn), 終點(diǎn)不定
            2.遍歷荷葉的最短路徑是一條鏈
            3.題目給出的坐標(biāo)順序是一個(gè)順時(shí)針方向的多邊形
            4.最短路徑不相交(畫一個(gè)四邊形, 利用三角形性質(zhì)可以觀察到)
            根據(jù)性質(zhì)1和2, 容易得出O(N^3)的方程, 很明顯會(huì)超時(shí)
            f[i][j] = min(f[k][j-1] + d[i][k]) (i!=k)
            -f[i][j]表示以i為起點(diǎn), 長度為j的最短路徑, 初始化f[i][1] = 0
            進(jìn)而考慮性質(zhì)3和4, 因而對于點(diǎn)1, 只能選擇相鄰的點(diǎn)2和n, 可以得到O(N^2)的方程
            f[i][j][0] = min{f[i+1][j-1][0] + d[i][i+1], f[i+1][j-1][1] + d[i][i+j-1]}
            f[i][j][1] = min{f[i][j-1][1] + d[i+j-1][i+j-2], f[i][j-1][1] + d[i+j-1][i]}
            -f[i][j][0]表示以i為起點(diǎn), 長度為j的最短路徑, f[i][j][1]表示以i為終點(diǎn), 長度為j的最短路徑, 初始化f[][1][] = 0
            -一個(gè)實(shí)現(xiàn)上的小優(yōu)化, 保證d[i][j](i<j)
            *注意靜態(tài)查錯(cuò), 區(qū)別變量名, 思考算法的過程應(yīng)該長于調(diào)試的過程
            *修正了測試點(diǎn)6

            火車進(jìn)站train[線性dp], 70min
            1.M <= 3 -> 可以分類討論
            2.只存在一條軌道, M只能決定軌道的長度 -> 如果同時(shí)在軌道中, i在j前的必要條件是i.s<=j.s和i.t<=j.t
            3.小站工作人員可以任意安排這些火車進(jìn)站的先后排列 -> 記憶化搜索
            4.小站允許幾輛火車同時(shí)進(jìn)站或出站 -> 所有條件都可取等號
            M = 1, f[i] = max(f[j] + 1)    (i.t <= j.s)
            M = 2, f[i][j] = max(f[j][k] + 1)  (i.t <= k.s)
            M = 3, f[i][j][k] = max(f[j][k][l] + 1) (i.t <= l.s)
            初始化f = 0, 利用vis記錄是否計(jì)算過, 各下標(biāo)互不相等
            *枚舉過程中注意剪枝, 利用i!=j和i.s<=j.s,i.t<=j.t逐層處理即可
            *[讀題]明確要求的是什么, 存在哪些條件, 寫list
            *[未驗(yàn)證]先對以進(jìn)站時(shí)間為第一關(guān)鍵字, 出站時(shí)間為第二關(guān)鍵字進(jìn)行快排, 然后直接遞推, 下標(biāo)滿足i < j < k < l

            快餐問題meal[資源分配(不妨認(rèn)為是背包)dp + 貪心優(yōu)化] -> 類似, usaco 3.4.4 rocker
            f[k][i][j]表示k條生產(chǎn)線生產(chǎn)i個(gè)漢堡, j個(gè)薯?xiàng)l時(shí)生產(chǎn)飲料的最大值, p[k][i][j]表示第k條生產(chǎn)線, 其他同.
            f[k][i][j] = max{f[k][i-ki][j-kj] + p[k][i][j]}
            sum[i] = sum[i-1] + A[i]
            初始化f[1][i][j] = p[1][i][j], f[2..n][i][j] = -1, 復(fù)雜度O(N*100^4)
            幾個(gè)優(yōu)化
            1.注意到每種物品總數(shù)小于100, 最大產(chǎn)量的上限是lim = min(100/a, 100/b, 100/c, sum[n]/(a*p1+b*p2+c*p3))
            2.為了避免數(shù)組越界, i的上限是min(lim*a, sum[n]/p1), j的上限min(lim*b, (A[k] - i*p1)/p2);
            ki的上限min(i, A[k]/p1), kj的上限min(j, (A[k] - ki*p1)/p2) -> 對于逗號右邊, 其實(shí)就是ki*p1+kj*p2<=A[k]
            3.將程序中的min/max用if語句替代
            4.對于每一套生產(chǎn)線, 盡量成套生產(chǎn)
            [反例]
            1 1 1
            2 3 7
            3
            15 16 17
            貪心可得最大值為3, 實(shí)際上15 = 7 + 3 + 3 + 2, 16 = 7 + 3 + 2 + 2 + 2, 17 = 7 + 7 + 3, 最大值為4;
            利用優(yōu)化1和2可以過5個(gè)測試點(diǎn), 優(yōu)化3可以進(jìn)一步優(yōu)化時(shí)間常數(shù), 利用優(yōu)化4可以過9個(gè)測試點(diǎn)
            AC程序參見[此文]http://hi.baidu.com/zijingningmeng/blog/item/2761617e2afe7ae32e73b3b3.html
            *調(diào)試過程中的主要問題是邊界溢出(沒有區(qū)分是否計(jì)算過), 變量名寫錯(cuò)
            *網(wǎng)上有說法表示去掉每種物品的件數(shù)限制后, 題目變成網(wǎng)絡(luò)流 -> gXX證偽
            *比賽的話, 不妨小數(shù)據(jù)(n<5)DP, 大數(shù)據(jù)(n>=5)貪心, 這樣應(yīng)該可以得到超過一半的分?jǐn)?shù)

            卡車更新問題truck, O(N^2), 1h
            f[i][k]表示第i年某車已使用了k年
            f[i][k] = max{f(i+1, 1) + R[0] - U[0] - C[k], f(i+1, k+1) + R[k] - U[k]}
            初始化f[][] = -1, 邊界條件f[i][k] = 0(i>N,k>K), 利用記憶化搜索實(shí)現(xiàn)
            記錄方案利用bool型數(shù)組prev[i][j][k]記錄是否購買新車, 遞歸即可
            *盡可能不換新車
            *利用樣例構(gòu)造樹, 寫出狀態(tài)即可得到方程
            *測試點(diǎn)1存在等價(jià)方案, 已修正數(shù)據(jù)(可能需要Special Judge)
            *f[i][j][k]中i和k可以唯一確定狀態(tài), 因而可以去掉中間1維

            選課course[樹形dp + 記錄方案], 多叉轉(zhuǎn)二叉實(shí)現(xiàn)
            f[i][j]表示以i為根節(jié)點(diǎn)的樹中, 選擇j門課
            f[i][j] = max(f[i.r][j], f[i.l][k] + f[i.r][j-k-1] + i.v) (0<=k<j)
            初始化f[][] = 0
            [記錄方案]
            利用print(i, j)遞歸, vis[i][j]表示是否已遍歷, [邊界]i∈[1, m], j∈[1, n]
            right[i][j]表示f[i][j]是否等于f[i.r][j]
            prev[i][j] = k表示f[i][j]由f[i.l][k],f[i.r][j-k-1]推得, 這時(shí)需記錄p[i] = 1
            從1到n判斷p[i]直接輸出即可.

            8.5

            廣場鋪磚問題floor[狀壓dp], 2h
            f[i][S] = Σf[i-1][S'] (S由S'推得)
            初始化f[1][0] = 1, f[h+1][0]即為答案
            對于每個(gè)f[i-1][S']利用dfs(當(dāng)前行i, 當(dāng)前行狀態(tài)s1, 下一行狀態(tài)s2, 當(dāng)前行指針k)尋找S
            if(!(s2 & 1<<k) && !(s2 & 1<<(k+1)))
             dp(i, s1, s2, k + 2);//存在連續(xù)兩個(gè)空位, 即橫放
            dp(i, s1, s2 ^ (1<<(k)), k + 1);//對當(dāng)前位取反, 即豎放
            利用int保存每一位的擺放方式, 1表示當(dāng)前行被上一行占用, 0表示當(dāng)前行未被占用
            [邊界]k = 0, 遞歸過程中k > w則退出

            硬木地板floor2[狀壓dp]
            f[i][S] = Σf[i-1][S'] (S由S'推得)
            初始化f[1][0] = 1, f[h+1][0]即為答案
            *實(shí)現(xiàn)無能, 最終放棄 -> 我應(yīng)該去學(xué)位運(yùn)算優(yōu)化BFS -_-
            *魚?!稜顟B(tài)壓縮》理解不能, NOI導(dǎo)刊朱全民文章code不全.
            *耗時(shí)最長的題目往往不是表面上的難題, 而是那些被簡單估計(jì)的難題

            posted @ 2011-08-05 20:51 Climber.pI 閱讀(577) | 評論 (0)編輯 收藏

            Problem List (7.13 ~ 7.20)

            7.13
            p1057 金明的預(yù)算方案[分組背包], 1.5h
            f[v] = max{f[v], f[v - c[i][j]] + w[i][j]}
            *注意讀題,主件的編號和物品編號相同,這里調(diào)了1h
            *注意逗號的使用

            @Ural p1018 Binary Apple Tree[樹形], 1.5h{大量參考題解}
            f[i][j] = max(f[tree[i].l][k] + f[tree[i].r][j-k-1] + tree[i].v)
            *初始化中使用-1標(biāo)記未計(jì)算(避免重復(fù)0)
            *遞歸建樹 -> 尋找兒子的過程可利用鄰接表優(yōu)化[未驗(yàn)證]
            *記憶化搜索f[t][q]初始化為0, 根節(jié)點(diǎn)值最后計(jì)算, 注意特殊情況0
            *特別注意, 把題目中的 邊權(quán) 轉(zhuǎn)換為 點(diǎn)權(quán), 以及q的相關(guān)變化

            7.15
            #p1051 選課[樹形DP], 1.5h
            f[i][j] = f[tree[i].r][j] (左子樹空)
                      f[tree[i].l][k]+f[tree[i].r][j-k-1]+tree[i].v (左子樹非空)
            *多叉樹轉(zhuǎn)二叉樹 -> 左兒子, 右兄弟
            if (!left[a]) tree[a].l = i;
            else tree[left[a]].r = i;
            left[a] = i;
            **記憶化搜索過程為什么不能直接返回int -> 實(shí)驗(yàn)證實(shí)會(huì)引起錯(cuò)誤, 原因不明 -> 盲目合并語句所致
                if (f[i][j] || i == 0 || j <= 0) return 0;
                應(yīng)為
                if (i == 0 || j <= 0) return 0;
                if (f[i][j]) return f[i][j] ;
                -> 合并此類控制邊界語句應(yīng)注意返回值
            **泛化背包做法 http://archive.cnblogs.com/a/2091585/

            p1087 sumsets[完全背包+統(tǒng)計(jì)方案數(shù)], 60min
            f[i][j] = f[i-1][j] + f[i][j-c[i]] (f[0][0] = 1)
            一開始盲目列表找遞推式, 嘗試無果. 后發(fā)現(xiàn)題目本意即完全背包問題, 2^k是物體, 實(shí)現(xiàn)時(shí)注意降維.
            *統(tǒng)計(jì)方案總數(shù)問題遞推式中max改為+, 注意f[0] = 1
            *此類問題注意高精度的實(shí)現(xiàn) 或者 mod(注意題目中要求, 如本題9位精度)
            *另一種方程 f[i] = f[i-1]         (i=2k+1) -> 已通過觀察得到
                               f[i-1] + f[i/2](i=2k)   -> 動(dòng)機(jī)是什么?

            p1079 數(shù)字三角形3[坐標(biāo)DP], 30min
            f[i][j] = max(f[i+1][j], f[i+1][j+1]) + A[i][j] (0 < j <= i <= n/2)
            通過分析可知, 指定點(diǎn)(n/2, n/2)前(i, i)必取, 而其后和一般數(shù)字三角做法相同, 終點(diǎn)為f[n/2][n/2]
            故最終答案Σf(i,i)_(0 < i < n/2) + f[n/2][n/2]
            *坐標(biāo)問題注意分析起點(diǎn)和終點(diǎn)的要求

            p1084 數(shù)字三角形4[坐標(biāo)DP], 10min
            (x, y)前: f1[i][j] = max(f1[i-1][j-1], f1[i-1][j]) + A[i][j] (0 < j <= i <= x)
            (x, y)后: f2[i][j] = max(f2[i+1][j], f2[i+1][j+1]) + A[i][j]
            分析可知, (x, y)前順推, 指定終點(diǎn)為(x, y), 起點(diǎn)必然為(1, 1), (x, y)后逆推, 指定終點(diǎn)為(x, y)
            故最終答案為f1[x][y] + f2[x][y] - A[x][y]

            p1076 數(shù)字三角形2[判定性DP], 30min
            f[i][j][(k+A[i][j])%100] = f[i+1][j][k] | f[i+1][j+1][k]
            通過增加維度轉(zhuǎn)化為判定性問題, 由于取模所以k的順序不確定, 因而用坐標(biāo)來控制順序

            7.16

            #p1048 田忌賽馬[貪心 + DP], 1.5h
            1.O(N + NlogN), [題解來自網(wǎng)絡(luò)]思想是這樣的, 先把各組馬的速度從大到小排序, 然后用田忌的馬順序與齊威王的馬比較
            if(田忌的馬快)比較下一對馬;
            else  if(田忌的馬慢)用田忌最慢的馬和齊威王的這匹馬賽
            else{
                從未進(jìn)行比賽的速度小的馬開始從后往前比
                if(田忌的馬快)      //這里是必須的,否則如果是90 73 71 和 90 70 70 ,那么沒有這個(gè)是
                    繼續(xù)往前比     //2-1,有了的話就是2+0,非常重要
                else 用這匹馬和剛才跑平的齊威王的馬比   
            //總之原則就是如果這匹馬不能贏,就讓他和比他快很多的馬比,這樣保持速度較快的馬
            }
            *while循環(huán)條件, f1 <= r1
            2.O(N^2 + NlogN), 來自:http://hi.baidu.com/lyltim/blog/item/57fccd1153ea851eb9127ba9.html
            [貪心分析]
            1、如果田忌剩下的馬中最強(qiáng)的馬都贏不了齊王剩下的最強(qiáng)的馬,那么應(yīng)該用最差的一匹馬去輸給齊王最強(qiáng)的馬。
            2、如果田忌剩下的馬中最強(qiáng)的馬可以贏齊王剩下的最強(qiáng)的馬,那就用這匹馬去贏齊王剩下的最強(qiáng)的馬。
            3、如果田忌剩下的馬中最強(qiáng)的馬和齊王剩下的最強(qiáng)的馬打平的話,可以選擇打平或者用最差的馬輸?shù)舯荣悺?br />[DP做法]
            f[i,j]=max{f[i-1,j]+g[n-(i-j)+1,i],f[i-1,j-1]+g[j,i]}
            其中g(shù)[i,j]表示田忌的馬和齊王的馬分別按照由強(qiáng)到弱的順序排序之后,田忌的第i匹馬和齊王的第j匹馬賽跑所能取得的盈利

            #p1402 烏龜棋[路徑DP], 1.5h
            f[i][j][k][l] = max(f[i-1][j][k][l], f[i][j-1][k][l], f[i][j][k-1][l], f[i][j][k][l-1]) + A[i+2j+3k+4l+1]
            以卡片數(shù)為階段, 狀態(tài)f[i][j][k][l]表示還剩下每種牌各多少張時(shí)得到的最大值, 注意起始位置
            *卡了1h因?yàn)楸?5的過河和08的傳紙條限制思維, 認(rèn)為以所在位置為階段, 想對空間降維
            *[降維條件]狀態(tài)各維度存在等量關(guān)系, 因而可減少時(shí)間復(fù)雜度, 但是不能改變空間復(fù)雜度

            #p1052 沒有上司的舞會(huì)[樹形DP], 1.5h
            f[i][0] = ∑max{f[j][0], f[j][1]} (j∈i.son), i不參加
            f[i][1] = ∑f[j][0] + tree[i].v   (j∈i.son), i參加
            [邊界]若i為葉節(jié)點(diǎn), f[i][0] = 0, f[i][1] = tree[i].v
            前半個(gè)小時(shí)寫完了多叉轉(zhuǎn)二叉, 證明了left[]的必要性.
            *狀態(tài)設(shè)計(jì)問題: 沒有區(qū)分i參加和不參加的情況, 并認(rèn)為f[i]由f[j](不取i, j是i的兒子)和f[k](取i, k是i的孫子)推得
            *葉節(jié)點(diǎn)的初始化, 對于f[i][]求和而非取最大值, 選取根節(jié)點(diǎn)而非葉節(jié)點(diǎn)(需要兩個(gè)數(shù)組映射)
            *由于30min時(shí)方程考慮不周, 導(dǎo)致多次修正, 因而卡了1h. 務(wù)必要先寫出正確方程.

            7.18

            p1134 CCR的中考之考前計(jì)劃[模擬], 50min
            語文題, 題目描述問題很大, 浪費(fèi)了0.5h, google了一個(gè)std之后得到正確題意. 題目是類似beads的模擬題, 將環(huán)從某處打斷, 使得兩端科目類型相同的天數(shù)最多.尋找相同科目的條件A[j+1] = 'w' || A[j+1] = A[i].
            *環(huán)狀問題的處理方法: 2n-1, 在本題中雙方向同時(shí)進(jìn)行不妨3n-2

            #p1088 treat[區(qū)間DP], 20min
            f[i][j] = max{f[i+1][j] + A[i] * (n+i-j), f[i][j-1] + A[j] * (n+i-j)} (0 < i < j <= n)
            f[i][j]表示[i, j]未取時(shí)的最大值, 初始化f[i][j] = A[i] * n, 以長度l為階段, 故 j = i+l-1
            *考慮第k次取數(shù), k = n - (i-j+1) + 1(包括這次), 昨天沒想到這點(diǎn)卡了很久
            *在網(wǎng)上找到了另外一種設(shè)置狀態(tài)的方法, 設(shè)f[i][j]是取i個(gè)數(shù), 左邊取j個(gè), 方程:
            f[i][j] = max(f[i - 1][j - 1] + i * A[j], f[i - 1][j] + i * A[n - (i - 1 - j)])
            -> 猜想動(dòng)機(jī): 存在等式 前 + 后 = 總數(shù), 狀態(tài)的設(shè)置都是為了描述著三個(gè)量.

            agirnet[Krusal], 20min
            復(fù)習(xí)并查集實(shí)現(xiàn)的Krusal

            p1307 聯(lián)絡(luò)員[Krusal],50min
            必選邊先使用set[find(e[i].u)] = find(e[i].v)合并, 并記錄權(quán)和, 然后按一般的Krusal做即可.
            *使用stdlib.h的qsort間接排序失敗, 原因不知(20min)
            *注意此時(shí)k++不能并入下一行語句中, 否則++k和k值不同導(dǎo)致輸入錯(cuò)誤:
                ++k,
                scanf("%d%d%d", &must[k].u, &must[k].v, &must[k].w);
                
            7.20

            p1113 魔族密碼[LIS模型], 40min, 6WA
            f[i] = max{f[j] + 1} (A[j]為A[i]前綴, 1 <= j < i)
            *注意最大值不一定在f[n]中, 需要對f[1] -> f[n]進(jìn)行循環(huán)檢查, 卡了30min

            p1187 小飛俠的游園方案[0/1背包], 15min
            f[i][j] = max(f[i-1][j], f[i-1][j - c[i]] + w[i])
            存在可能未裝滿的情況, 故循環(huán)檢查f[n][]即可

            #p1190 積木城堡[背包DP], 1.5h, 6WA
            f[k][j] = f[k][j - w[i]] (j - w[i] >= 0)
            類似分組背包的做法, 記錄每組物品的所有可能值, 若f[1..k][V]同時(shí)為true, 則V為最值. 也可以在讀入時(shí), 循環(huán)檢查每組物品的可能值.
            *注意讀題, 尤其是各種數(shù)據(jù)范圍, 不要重復(fù)去年第二題!!!
            *讀入時(shí)注意MAXn+1, 留意-1的情況; 顯然答案不會(huì)超過所有城堡的最小高度(而非最大).
            *題目中并沒有強(qiáng)調(diào)按順序取積木, 因而一開始打了模擬, 之后手賤去Google. 對于這類問題, 在提交后若發(fā)現(xiàn)則應(yīng)繼續(xù)思考. 此外不要給題目增加條件.
            **注意這類確定各組物品所有可能值寫法 和 最優(yōu)值寫法的區(qū)別
            *一組測試數(shù)據(jù):
            5
            87 76 65 54 32 21 23 -1
            64 75 25 63 76 23 75 13 64 23 -1
            09 78 76 46 32 45 23 -1
            23 34 45 -1
            12 34 23 -1

            p1213 嵌套矩形[LIS模型/DAG最長路], 1h, 9WA
            (1)f[i] = max(f[j] + 1) (rect[i]可嵌套rect[j])
            *初始化f[] = 1; 初始化為0, 輸出+1會(huì)導(dǎo)致錯(cuò)誤, 原因不知.
            -> 另一種寫法(by Ylen): f[0] = 0, f[] = INT_MAX;
            *注意題目沒有強(qiáng)調(diào)矩形間存在順序, 因而存在后效性. 易知面積小的矩形不會(huì)嵌套面積大的矩形, 因而以面積為關(guān)鍵字對rect進(jìn)行間接排序.
            (2)f[i] = max(f[j] + 1 | (i,j)∈G)
            若rect[i]可嵌套rect[j], 則建立一條從i到j(luò)的邊, 求最長路即可

            posted @ 2011-07-21 15:55 Climber.pI 閱讀(313) | 評論 (0)編輯 收藏

            LGOI 2011 初賽備考

            記得去年在紙上寫過一份這樣的東西,迎來的是exhaustive fail.需要明確復(fù)習(xí)重點(diǎn)是數(shù)據(jù)結(jié)構(gòu)和算法, 考場上要注意出題規(guī)律和草稿的清晰性. 簡單復(fù)習(xí)大概用了6個(gè)番茄鐘.

            1.表達(dá)式樹
            [中綴] (a + b) * c + d * c
            (((a + b) * c) + (d * c))
            [前綴] +(*(+(a b) c) * (d c))
            + * + a b c * d c
            [計(jì)算方法1] 壓棧(前綴 -> 從后向前)
            [計(jì)算方法2] 括號(opt后) -> 中綴

            2.二分查找的平均次數(shù) log(n+1)-1

            3.heap的實(shí)現(xiàn)
            [up] while(k > 1) 比較 交換(h[k], h[k/2])
            [down] while(2 * k <= n) 比較 交換(h[k], h[2k + 1(小于n的話)])

            4.排序算法的穩(wěn)定性
            [穩(wěn)定]插入排序、冒泡排序、歸并排序、分配排序(桶式、基數(shù))
            [不穩(wěn)定的]直接選擇排序、堆排序、shell排序、快速排序都是不穩(wěn)定的排序算法。
            [穩(wěn)定排序]http://www.jpk.pku.edu.cn/pkujpk/course/sjjg/chapter7/01/05.html
            [排序原理]http://hi.baidu.com/cuifenghui/blog/item/0587932b039557f9e7cd4051.html

            5.出棧序列
            一個(gè)數(shù)列滿足條件,當(dāng)且僅當(dāng)每一段單調(diào)遞減數(shù)列要么不存在空缺(即為公差-1的等差數(shù)列),要么它的空缺在之前全部已經(jīng)出現(xiàn)。

            [充要條件]若出棧序列合法,則一定不存在1<=i<j<k<=n,使s[j]<s[k]<s[i]

            6.鄰接表的插入操作(鏈表的插入)
            next[e] = first[u[e]]; first[u[e]] = e;

            7.邏輯表達(dá)式恒值
            注意符號, 轉(zhuǎn)化為分情況表示的函數(shù)

            8.叉積的計(jì)算(特別注意第二個(gè)負(fù)號)
            |i j k|
            |a1 a2 a3|=i|a2 a3|-j|a1 a3|+k|a1 a2|
            |b1 b2 b3|  |b2 b3|  |b1 b3|  |b1 b2|

            9.閱讀程序注意意圖, 草稿的清晰度(減少亂劃)

            [RAM]http://baike.baidu.com/view/3558.htm
            隨機(jī)存儲(chǔ): 訪問時(shí)間與位置無關(guān)
            [Hash]http://www.nocow.cn/index.php/%E6%95%A3%E5%88%97%E8%A1%A8
            [拓?fù)渑判?DAG)]http://zh.wikipedia.org/wiki/%E6%8B%93%E6%92%B2%E6%8E%92%E5%BA%8F\

            posted @ 2011-05-14 19:21 Climber.pI 閱讀(4734) | 評論 (0)編輯 收藏

            僅列出標(biāo)題
            共8頁: 1 2 3 4 5 6 7 8 
            国产无套内射久久久国产| 国内精品人妻无码久久久影院 | 2021国产成人精品久久| 国产2021久久精品| 久久无码AV中文出轨人妻| 久久综合给久久狠狠97色| 精品无码久久久久久久久久| 亚洲中文精品久久久久久不卡| 久久中文字幕一区二区| 久久无码AV中文出轨人妻| 色综合久久综合网观看| 97精品伊人久久久大香线蕉| 伊人久久综合成人网| 久久91这里精品国产2020| 久久久久久亚洲精品成人| 亚洲精品高清一二区久久| 久久亚洲国产欧洲精品一| 亚洲国产精品无码久久SM| 理论片午午伦夜理片久久| 99久久国产免费福利| 999久久久无码国产精品| 久久久噜噜噜久久中文字幕色伊伊| 伊人久久综合热线大杳蕉下载| 亚洲精品无码久久一线| 亚洲精品国产综合久久一线| 久久久久国产| 精品国产婷婷久久久| 99久久99久久| 91精品国产综合久久精品| 久久天天躁狠狠躁夜夜躁2O2O | 久久99亚洲网美利坚合众国| 中文精品99久久国产| 四虎亚洲国产成人久久精品| 久久精品国产色蜜蜜麻豆| 一级做a爰片久久毛片人呢| 久久成人影院精品777| 久久人人爽人人爽人人AV东京热| 久久精品国产亚洲AV影院| 狠狠色婷婷久久综合频道日韩 | 91精品国产综合久久久久久| 久久99精品国产|