• <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>
            RQNOJ187 巧置擋板
            ———————————————————————————————————————————————————
            【背景(神犇不要囧視,3x)】
            本沙茶最近開始猛攻搜索、近似、隨機等算法,目標是A掉AHOI2012的后3題(在哪跌倒就從哪爬起)。昨天晚上找到這題,發現是搜索,于是開始捉……結果被折騰了一晚上加一上午才A掉,不過,看在這題可以系統性的反映DFS優化的一般步驟,忍了……另外,這題是本沙茶在RQNOJ上通過的第400題……回想起通過第300題的時候已經是近三年半之前了……真頹廢啊……
            ———————————————————————————————————————————————————
            普通DFS(不加迭代)的優化方法主要有:
            (1)可行性剪枝,如果遇到已經無法產生可行解的情況就剪枝,有時候,可行性剪枝也可以指在搜索過程中對不合法情況的剔除;
            (2)最優性剪枝:如果遇到已經無法產生比目前得到的最優解還要優的解的情況就剪枝,這其中包括啟發式最優性剪枝(即分支限界),對目前解的進展情況作樂觀估計,如果估計值都不能超越目前的最優解,則剪枝;
            (3)通過改變搜索順序,盡早得出較優解,從而為后面的剪枝提供余地;
            (4)通過預處理等手段,提前得到啟發值或者較優解,為后面的剪枝提供余地;

            一般步驟:
            (1)預處理,當然是寫在最前面,在搜索前得到啟發值等東東;
            (2)搜索過程中,先寫最優性剪枝(包括已經到達搜索終點了,也應該判斷一下,提前排除不是最優解的情況);
            (3)再判定搜索終點,如果到了,也不要馬上更新解,而是要判定這個解是否符合要求,再更新;
            (4)若未到終點,再寫可行性剪枝;
            (5)最后寫搜索過程,包括需要改變搜索順序的情況。

            注意事項:數組的分層問題。
            這是一個很嚴重的問題,因為分層出錯很可能會導致一些很怪的錯誤出現,難以發現。在搜索題的調試技巧這一篇中,已經提到了這個問題,本題又涉及到了。
            一般來說,搜索過程中使用的數組(包括變量,可以視為零維數組)可以分為以下三類:
            (1)在搜索過程中,只會引用其值,不會修改的數組(比如預處理中得到的那些東東),相當于常量;
            (2)在搜索過程中,會改變其值,但在搜索完畢后能改回原值的數組;
            (3)在搜索過程中,會改變其值,且在搜索完畢后也改不回原值的數組。
            對于(1)(2)類數組,不需分層,但對于第(3)類數組一定要分層。這是因為這些數組在多層搜索中都需要修改,而且搜索完了也改不回來,如果不分層,則當后面的搜索完畢以后,要繼續搜索前面的,引用的將是后面的值,就會出錯。
            對于第(3)類數組,有的已經“自然分層”(每層搜索修改的元素都不一樣),比如本題代碼中的R[][]、C[][]。然而有的并沒有自然分層,比如本題的len、pos[]、tmp[]等,因此對于這些數組,需要再加一維,對于不同層使用該維不同的元素即可。

            下面是本題的算法:
            使用DFS搜索每個位置的擋板是否需要放。搜索時,先搜豎的再搜橫的,由于題目要求每個連通塊都必須是矩形,因此對于豎的,如果該位置的上方兩個相鄰位置的橫的沒有全放(包括只放了一個),則該位置的豎的放不放取決于其上一行對應位置的豎的有沒有放(第一行除外),如果兩個橫的都放了,則這里的豎的既可以放也可以不放(先搜不放的情況)。當然,一行的兩個1之間必須至少有一個豎的,這是可行性限制。在搜橫的的時候,按照該行所放的豎的,分成若干段,顯然每一段要么下面都用橫的封上,要么一個都不封上。其中,如果該段所在的連通塊里面有1,且下一行對應位置也有1,則必須封上;若該段所在連通塊里面沒有1,則不能封上(因為不能有一個連通塊里一個1都沒有),否則可以自由選擇封還是不封(當然也是先搜不封的)。這樣一直搜到最后一行的豎的后,還要判斷最后一行有沒有連通塊里沒1,若沒有,則為一個可行解。啟發式優化:設D[i]為第i行及以后至少要幾個擋板(若某行有K個1,則至少需要(K-1)個豎的;若某列有K個1,則至少需要(K-1)個橫的,累加起來即可,顯然這是樂觀估計),D[i]可以預處理出來,當做啟發值。

            代碼:
            #include <iostream>
            #include 
            <stdio.h>
            #include 
            <stdlib.h>
            #include 
            <string.h>
            using namespace std;
            #define re(i, n) for (int i=0; i<n; i++)
            #define re1(i, n) for (int i=1; i<=n; i++)
            #define re2(i, l, r) for (int i=l; i<r; i++)
            #define re3(i, l, r) for (int i=l; i<=r; i++)
            #define rre(i, n) for (int i=n-1; i>=0; i--)
            #define rre1(i, n) for (int i=n; i>0; i--)
            #define rre2(i, r, l) for (int i=r-1; i>=l; i--)
            #define rre3(i, r, l) for (int i=r; i>=l; i--)
            const int MAXN = 35, INF = ~0U >> 2;
            int n, m, D[MAXN], len[MAXN], pos[MAXN][MAXN], tmp[MAXN][MAXN], res = INF;
            bool A[MAXN][MAXN], C[MAXN][MAXN], R[MAXN][MAXN], S[MAXN][MAXN][MAXN][MAXN];
            void dfs0(int No, int v, int sum, bool FF);
            void init()
            {
                scanf(
            "%d%d"&n, &m); int x;
                re(i, n) re(j, m) {scanf(
            "%d"&x); A[i][j] = x;}
            }
            void prepare()
            {
                re(i, n) re(j, m) {
                    S[i][j][i][j] 
            = A[i][j];
                    re2(k, i
            +1, n) S[i][j][k][j] = A[k][j] || S[i][j][k - 1][j];
                    re2(k, j
            +1, m) S[i][j][i][k] = A[i][k] || S[i][j][i][k - 1];
                    re2(k, i
            +1, n) re2(k0, j+1, m) S[i][j][k][k0] = A[k][k0] || S[i][j][k - 1][k0] || S[i][j][k][k0 - 1];
                }
                
            int sum;
                re(i, n) {
                    D[i] 
            = 0;
                    re2(j, i, n) {sum 
            = 0; re(k, m) if (A[j][k]) sum++if (sum) D[i] += sum - 1;}
                    re(k, m) {sum 
            = 0; re2(j, i, n) if (A[j][k]) sum++if (sum) D[i] += sum - 1;}
                }
            }
            void dfs1(int No, int v, int sum)
            {
                
            if (sum + D[No + 1>= res) return;
                
            if (v == len[No] + 1) dfs0(No + 10, sum, 1); else if (tmp[No][v] != 1) dfs1(No, v + 1, sum); else {
                    
            int l, r, sum0 = sum;
                    
            if (v) l = pos[No][v - 1+ 1else l = 0;
                    
            if (v == len[No]) r = m - 1else r = pos[No][v];
                    re3(j, l, r) R[No][j] 
            = 0; dfs1(No, v + 1, sum);
                    re3(j, l, r) {R[No][j] 
            = 1; sum0++;} dfs1(No, v + 1, sum0);
                }
            }
            void dfs0(int No, int v, int sum, bool FF)
            {
                
            if (sum + D[No + 1>= res) return;
                
            bool FF0; if (A[No][v]) {if (!FF) returnelse FF0 = 0;} else FF0 = FF;
                
            if (v == m - 1) {
                    
            if (No == n - 1) {
                        len[No] 
            = 0; re(i, m-1if (C[No][i]) pos[No][len[No]++= i;
                        
            int l, r, x; bool FFF = 1;
                        re3(i, 
            0, len[No]) {
                            
            if (i) l = pos[No][i - 1+ 1else l = 0;
                            
            if (i == len[No]) r = m - 1else r = pos[No][i];
                            x 
            = 0; rre(j, No) if (R[j][l]) {x = j + 1break;}
                            
            if (!S[x][l][No][r]) {FFF = 0break;}
                        }
                        
            if (FFF) res = sum;
                        
            return;
                    }
                    len[No] 
            = 0; re(i, m-1if (C[No][i]) pos[No][len[No]++= i;
                    
            int l, r, x, sum0 = sum;
                    re3(i, 
            0, len[No]) {
                        
            if (i) l = pos[No][i - 1+ 1else l = 0;
                        
            if (i == len[No]) r = m - 1else r = pos[No][i];
                        x 
            = 0; rre(j, No) if (R[j][l]) {x = j + 1break;}
                        
            if (S[x][l][No][r] && S[No + 1][l][No + 1][r]) {
                            tmp[No][i] 
            = 2; re3(j, l, r) {sum0++; R[No][j] = 1;}
                        } 
            else if (S[x][l][No][r]) {
                            tmp[No][i] 
            = 1; re3(j, l, r) R[No][j] = 0;
                        } 
            else {
                            tmp[No][i] 
            = 0; re3(j, l, r) R[No][j] = 0;
                        }
                    }
                    dfs1(No, 
            0, sum0);
                } 
            else if (No && (!R[No - 1][v] || !R[No - 1][v + 1])) {
                    
            if (C[No - 1][v]) {C[No][v] = 1; dfs0(No, v + 1, sum + 11);} else {C[No][v] = 0; dfs0(No, v + 1, sum, FF0);}
                } 
            else {
                    C[No][v] 
            = 0; dfs0(No, v + 1, sum, FF0);
                    C[No][v] 
            = 1; dfs0(No, v + 1, sum + 11);
                }
            }
            void pri()
            {
                printf(
            "%d\n", res);
            }
            int main()
            {
                init();
                prepare();
                dfs0(
            0001);
                pri();
                
            return 0;
            }


            久久噜噜久久久精品66| 久久99国产精品久久久| 久久99精品国产麻豆不卡| 久久久无码人妻精品无码| 狠狠色丁香婷婷久久综合| 性做久久久久久免费观看| 精品人妻伦九区久久AAA片69| 成人精品一区二区久久久| 国产精品午夜久久| 久久久精品人妻无码专区不卡| 日本福利片国产午夜久久| 久久国产成人精品国产成人亚洲| 一本一道久久精品综合| 国产精品va久久久久久久| 欧美午夜A∨大片久久 | 久久99精品久久久久久hb无码| 亚洲av日韩精品久久久久久a| 色婷婷综合久久久久中文| 久久国产乱子伦精品免费强| 91精品国产91久久久久久蜜臀| 99久久精品久久久久久清纯| 欧美亚洲另类久久综合婷婷| 亚洲精品久久久www| 久久夜色精品国产欧美乱| 91久久婷婷国产综合精品青草| 成人亚洲欧美久久久久| 久久亚洲AV成人无码软件| 国产精品欧美久久久天天影视 | 色综合久久久久综合体桃花网| 久久久噜噜噜久久中文福利| 伊人久久大香线焦综合四虎| 亚洲欧美国产日韩综合久久| 久久精品国产免费观看| 国产成人久久精品麻豆一区| 久久人人添人人爽添人人片牛牛| 99久久婷婷国产综合亚洲| 久久亚洲国产成人精品无码区| 久久精品www人人爽人人| 国产综合精品久久亚洲| 久久精品a亚洲国产v高清不卡| 污污内射久久一区二区欧美日韩|