• <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>
            Tim's Programming Space  
            Tim's Programming Space
            日歷
            <2009年11月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345
            統計
            • 隨筆 - 20
            • 文章 - 1
            • 評論 - 40
            • 引用 - 0

            導航

            常用鏈接

            留言簿(3)

            隨筆檔案

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             
            NOIP2009最后一題。
            看到題的時候直接就想到了DancingLinks,但是。。。很后悔是,原來想學的時候覺得難寫就沒寫了。
            不過考試時裸搜加最優性剪枝有95分,也很不錯了。
            DacingLinks其實就是十字鏈表,用于求解精確覆蓋問題:對于一個0-1矩陣,選取一些行使得每列有且只有一個1。
            把數獨轉換為這樣一個模型以后就可以用DacingLinks快速的搜索了。
            搜索時每次選擇1的個數最少的那列,枚舉那列上選取的某行,再把那行其他位置有1的列刪除,接著繼續搜索?;厮輹r再還原改動。
            對于數獨而言,一共有9*9個格子,每個格子可以填9個數,所以在0-1矩陣里就有9*9*9=729行,表示在某個格子里填某個數。
            同時在某個位置填了某個數后,那個數所在的列,行,9宮格也不能填那個數了,同時那個格子也不能填其他數了,所以某行填某個數有9*9,某列填某個數有9*9,某個9宮格填某個數9*9,某個位置填數9*9,一共就用324列。
            建好這樣一個圖后,就直接用DancingLinks搜索,因為相比一般的裸搜冗余很少,所以速度非常快。
            /*
             * $File: sudoku.cpp
             * $Date: Sun Nov 29 20:22:32 2009 CST
             
            */

            #include 
            <iostream>
            #include 
            <cstring>
            #include 
            <cstdio>
            #include 
            <cstdlib>
            #include 
            <cmath>

            #define LENGTH 9
            #define SQRLEN 3
            #define MAXN (LENGTH*LENGTH*LENGTH)
            #define MAXM (4*LENGTH*LENGTH)
            #define MAXNODE MAXN*MAXM

            int max(int a,int b){
                
            return a>b?a:b;
            }
            int map[MAXN][MAXM];
            int U[MAXNODE],D[MAXNODE],L[MAXNODE],R[MAXNODE];
            int S[MAXNODE],C[MAXNODE],ROW[MAXNODE];
            int n,m;
            int h = 0;//the Leftest and Upest node 
            int a[LENGTH][LENGTH];
            void Init(){
                freopen(
            "sudoku.in","r",stdin);
                freopen(
            "sudoku.out","w",stdout);
                
            for (int i = 0; i<LENGTH; i++)
                    
            for (int j = 0; j<LENGTH; j++)
                        scanf(
            "%d",&a[i][j]);
            }
            int Row(int x,int y,int num){
                
            return (x*LENGTH+y)*LENGTH+num-1;
            }

            #define SEC_POS 0
            #define SEC_ROW 1
            #define SEC_COL 2
            #define SEC_SQR 3
            #define PER_SEC LENGTH*LENGTH

            void Fill(int x,int y,int num){
                
            int row = Row(x,y,num);
                map[row][SEC_POS
            *PER_SEC+x*LENGTH+y] = 1;
                map[row][SEC_ROW
            *PER_SEC+x*LENGTH+num-1= 1;
                map[row][SEC_COL
            *PER_SEC+y*LENGTH+num-1= 1;
                map[row][SEC_SQR
            *PER_SEC+((x/SQRLEN)*SQRLEN+(y/SQRLEN))*LENGTH+num-1= 1;
            }
            int cnt;
            void BuildGraph(){
                
            // Build The 0-1 Matrix
                for (int i = 0; i<LENGTH; i++)
                    
            for (int j = 0; j<LENGTH; j++)
                    
            if (a[i][j])
                            Fill(i,j,a[i][j]);
                        
            else for (int k = 1; k<=LENGTH; k++)
                            Fill(i,j,k);

                
            // Build Dacing Links
                n = MAXN,m = MAXM;

                
            for (int i = 0; i<n; i++)
                    
            for (int j = 0; j<m; j++)
                        
            if (map[i][j])
                            map[i][j] 
            = ++cnt;
                
            int tmp,s = 0,t = 0;
                
            for (int i = 0; i<n; i++){
                    
            for (int j = 0; j<m; j++)
                        
            if (tmp=map[i][j])
                            L[tmp] 
            = t, S[tmp] = i,t = tmp;
                    
            for (int j = m-1; j>=0; j--)
                        
            if (tmp=map[i][j])
                            R[tmp] 
            = s, s =tmp;
                    R[t] 
            = s,L[s] = t;
                }
                
            for (int j = 0; j<m; j++){
                    t 
            = ++cnt;
                    
            for (int i = 0; i<n; i++)
                        
            if (tmp=map[i][j])
                            U[tmp] 
            = t, t = tmp,C[tmp] = cnt, ++S[cnt];
                    s 
            = cnt;
                    
            for (int i = n-1; i>=0; i--)
                        
            if (tmp=map[i][j])
                            D[tmp] 
            = s, s = tmp;
                    D[cnt] 
            = s,U[cnt] = t;
                }
                
            for (int i = cnt-m+1; i<=cnt; i++)
                    L[i] 
            = i-1;
                
            for (int i = cnt; i>cnt-m; i--)
                    R[i] 
            = i+1;
                R[h] 
            = cnt-m+1,L[h] = cnt;
                L[cnt
            -m+1= R[cnt] = h;
            }
            int ans[MAXM+1];
            void Cover(int c){
                L[R[c]] 
            = L[c],R[L[c]] = R[c];
                
            for (int i = D[c];i!=c;i = D[i])
                    
            for (int j = R[i];j!=i;j = R[j])
                        U[D[j]] 
            = U[j],D[U[j]] = D[j],S[C[j]]--;
            }
            void UnCover(int c){
                
            for (int i = U[c];i!=c;i=U[i])
                    
            for (int j = L[i];j!=i;j = L[j])
                        S[C[j]]
            ++,U[D[j]] = D[U[j]] = j;
                L[R[c]] 
            = R[L[c]] = c;
            }
            int Ans = -1;
            int ScoreTable[LENGTH][LENGTH] = {
                {
            6,6,6,6,6,6,6,6,6},
                {
            6,7,7,7,7,7,7,7,6},
                {
            6,7,8,8,8,8,8,7,6},
                {
            6,7,8,9,9,9,8,7,6},
                {
            6,7,8,9,10,9,8,7,6},
                {
            6,7,8,9,9,9,8,7,6},
                {
            6,7,8,8,8,8,8,7,6},
                {
            6,7,7,7,7,7,7,7,6},
                {
            6,6,6,6,6,6,6,6,6}
            };
            int score(int c){
                
            int t = S[c];
                
            int num = t%LENGTH+1;
                
            int x = t/LENGTH/LENGTH%LENGTH;
                
            int y = t/LENGTH%LENGTH;
                
            return num*ScoreTable[x][y];
            }
            int ansmap[LENGTH][LENGTH];
            //this function is not used in this program, but it gives out a solution of a sudoku
            void GetAns(int step){
                memset(ansmap,
            0,sizeof(ansmap));
                
            for (int i = 0; i<step; i++){
                    
            int t = ans[i];
                    
            int x = t/LENGTH/LENGTH%LENGTH;
                    
            int y = t/LENGTH%LENGTH;
                    
            int num = t%LENGTH+1;
                    ansmap[x][y] 
            = num;
                }
            }
            void search(int step,int v){
                
            if (R[h] == h){
                    Ans 
            = max(Ans,v);
                
            /*    GetAns(step);
                    for (int i = 0; i<LENGTH; i++){
                        for (int j = 0; j<LENGTH; j++)
                            printf("%d ",ansmap[i][j]);
                        printf("\n");
                    }
                    printf("\n");
            */
                    
            return;
                }
                
            int c,s = MAXNODE;
                
            for (int i = R[h];i!=h; i=R[i])
                    
            if (S[i]<s)
                        s 
            = S[i],c = i;
                Cover(c);
                
            for (int i = D[c];i!=c;i=D[i]){
                    ans[step] 
            = S[i];
                    
            for (int j = R[i];j!=i;j = R[j])
                        Cover(C[j]);
                    search(step
            +1,v+score(i));
                    
            for (int j = L[i];j!=i;j = L[j])
                        UnCover(C[j]);
                }
                UnCover(c);
            }
            void DancingLinks(){
                search(
            0,0);
                printf(
            "%d\n",Ans);
            }
            void Solve(){
                BuildGraph();
                DancingLinks();
            }
            int main(){
                Init();
                Solve();
                
            return 0;
            }

            posted on 2009-11-30 21:52 TimTopCoder 閱讀(3578) 評論(10)  編輯 收藏 引用
            評論:
            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  創意產品批發 Posted @ 2009-12-01 15:22
              學習了。謝謝!  回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  jamesbend Posted @ 2010-01-05 14:53
              tim 神牛orz
                回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  jamesbend Posted @ 2010-01-05 14:54
              tim 神牛orz  回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  jamesbend Posted @ 2010-01-06 21:46
              tim 神牛。。。。。。  回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  forestkeeper Posted @ 2010-01-09 19:34
              順提下dancing linking的入門題是hdu1017.。。。。  回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  EleMenTLz Posted @ 2010-05-03 17:19
              牛X 當差裸搜+剪枝95 我裸搜25.  回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  Keira Posted @ 2012-07-10 04:23
              跪拜神牛,map[][]數組運用的太巧妙了,在處理精確覆蓋的同時也完成了節點與鏈表之間的O(1)映射。  回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  Keira Posted @ 2012-07-10 08:39
              神牛求教一下ScoreTable的作用是什么?這段沒有看懂....  回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  Keira Posted @ 2012-07-10 09:05
              再求神牛解釋以下數組S和C的作用?沒怎么看明白,我知道在AlgorithmX的啟發式搜索方法中,需要每次尋找非零計數最小的列開始搜索,看情況好像數組S是用來保存每列的非零元素計數的,但是又好像S還有其他的用途?另外在UDLR初始化的最后幾句,就是cnt-m+1這些語句又是干嘛的呢?希望神牛能夠不吝賜教!感激不禁,謝謝!
                回復  更多評論   

            • # re: Sudoku - DancingLinks (數獨DancingLinks搜索優化算法)  zxytim Posted @ 2012-07-28 13:11
              @Keira
              ScoreTable是NOIP靶形數獨那題用的。。。
              cnt-m+1什么的是在鏈最上面那層的鏈表,標號是那樣的而已。。。你自己像個方法建立這個鏈表就行了。。。
              S除了記列大小以外我也沒看懂在求score的時候用它干嘛。。。代碼年久失修。。。
              C記每個點的列。

              PS:居然還有人看。。。太感動了。。。  回復  更多評論   

             
            Copyright © TimTopCoder Powered by: 博客園 模板提供:滬江博客
            色综合久久中文综合网| 亚洲欧美国产精品专区久久| 亚洲国产另类久久久精品| 久久人妻少妇嫩草AV蜜桃| 久久精品人人做人人爽电影| 久久www免费人成看片| 国产三级久久久精品麻豆三级| 99久久久国产精品免费无卡顿| 国产69精品久久久久99尤物| 久久伊人色| 国产精品9999久久久久| 色综合久久久久综合99| 久久亚洲精品无码AV红樱桃| 精品久久人人做人人爽综合| 午夜久久久久久禁播电影| 91精品国产综合久久香蕉 | 曰曰摸天天摸人人看久久久| 日本国产精品久久| av午夜福利一片免费看久久| 一本色道久久88综合日韩精品 | 久久久久国产日韩精品网站| 亚洲精品无码久久千人斩| 国产成人久久777777| 嫩草伊人久久精品少妇AV| 久久久久亚洲AV无码专区桃色| 久久青青草原精品国产| 热99RE久久精品这里都是精品免费 | 国产精品久久成人影院| 国产69精品久久久久9999APGF | www.久久热| 亚洲va国产va天堂va久久| 久久99这里只有精品国产| 久久久久国产精品麻豆AR影院| 99久久成人18免费网站| 一本一本久久A久久综合精品| 老司机午夜网站国内精品久久久久久久久 | 精品久久人人爽天天玩人人妻| 国产亚洲美女精品久久久 | 久久久久久久综合日本| 久久久不卡国产精品一区二区| 久久久精品人妻无码专区不卡|