• <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
            日歷
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567
            統(tǒng)計(jì)
            • 隨筆 - 20
            • 文章 - 1
            • 評(píng)論 - 40
            • 引用 - 0

            導(dǎo)航

            常用鏈接

            留言簿(3)

            隨筆檔案

            文章檔案

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

             
            NOIP2009最后一題。
            看到題的時(shí)候直接就想到了DancingLinks,但是。。。很后悔是,原來(lái)想學(xué)的時(shí)候覺(jué)得難寫就沒(méi)寫了。
            不過(guò)考試時(shí)裸搜加最優(yōu)性剪枝有95分,也很不錯(cuò)了。
            DacingLinks其實(shí)就是十字鏈表,用于求解精確覆蓋問(wèn)題:對(duì)于一個(gè)0-1矩陣,選取一些行使得每列有且只有一個(gè)1。
            把數(shù)獨(dú)轉(zhuǎn)換為這樣一個(gè)模型以后就可以用DacingLinks快速的搜索了。
            搜索時(shí)每次選擇1的個(gè)數(shù)最少的那列,枚舉那列上選取的某行,再把那行其他位置有1的列刪除,接著繼續(xù)搜索。回溯時(shí)再還原改動(dòng)。
            對(duì)于數(shù)獨(dú)而言,一共有9*9個(gè)格子,每個(gè)格子可以填9個(gè)數(shù),所以在0-1矩陣?yán)锞陀?*9*9=729行,表示在某個(gè)格子里填某個(gè)數(shù)。
            同時(shí)在某個(gè)位置填了某個(gè)數(shù)后,那個(gè)數(shù)所在的列,行,9宮格也不能填那個(gè)數(shù)了,同時(shí)那個(gè)格子也不能填其他數(shù)了,所以某行填某個(gè)數(shù)有9*9,某列填某個(gè)數(shù)有9*9,某個(gè)9宮格填某個(gè)數(shù)9*9,某個(gè)位置填數(shù)9*9,一共就用324列。
            建好這樣一個(gè)圖后,就直接用DancingLinks搜索,因?yàn)橄啾纫话愕穆闼讶哂嗪苌伲运俣确浅?臁?br>
            /*
             * $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) 評(píng)論(10)  編輯 收藏 引用
            評(píng)論:
            • # re: Sudoku - DancingLinks (數(shù)獨(dú)DancingLinks搜索優(yōu)化算法)  創(chuàng)意產(chǎn)品批發(fā) Posted @ 2009-12-01 15:22
              學(xué)習(xí)了。謝謝!  回復(fù)  更多評(píng)論   

            • # re: Sudoku - DancingLinks (數(shù)獨(dú)DancingLinks搜索優(yōu)化算法)  jamesbend Posted @ 2010-01-05 14:53
              tim 神牛orz
                回復(fù)  更多評(píng)論   

            • # re: Sudoku - DancingLinks (數(shù)獨(dú)DancingLinks搜索優(yōu)化算法)  jamesbend Posted @ 2010-01-05 14:54
              tim 神牛orz  回復(fù)  更多評(píng)論   

            • # re: Sudoku - DancingLinks (數(shù)獨(dú)DancingLinks搜索優(yōu)化算法)  jamesbend Posted @ 2010-01-06 21:46
              tim 神牛。。。。。。  回復(fù)  更多評(píng)論   

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

            • # re: Sudoku - DancingLinks (數(shù)獨(dú)DancingLinks搜索優(yōu)化算法)  EleMenTLz Posted @ 2010-05-03 17:19
              牛X 當(dāng)差裸搜+剪枝95 我裸搜25.  回復(fù)  更多評(píng)論   

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

            • # re: Sudoku - DancingLinks (數(shù)獨(dú)DancingLinks搜索優(yōu)化算法)  Keira Posted @ 2012-07-10 08:39
              神牛求教一下ScoreTable的作用是什么?這段沒(méi)有看懂....  回復(fù)  更多評(píng)論   

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

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

              PS:居然還有人看。。。太感動(dòng)了。。。  回復(fù)  更多評(píng)論   


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


             
            Copyright © TimTopCoder Powered by: 博客園 模板提供:滬江博客
            要久久爱在线免费观看| 国产成人精品综合久久久| 久久无码国产| 国产精品女同一区二区久久| 99久久成人国产精品免费| 亚洲日韩中文无码久久| 伊人色综合九久久天天蜜桃| 国内精品久久久久久久亚洲 | 久久成人精品| A级毛片无码久久精品免费| 热久久国产精品| 国产综合成人久久大片91| 狠狠色综合网站久久久久久久 | 久久久噜噜噜久久| 久久无码精品一区二区三区| 久久久久99精品成人片牛牛影视 | 亚洲精品久久久www| 中文字幕亚洲综合久久菠萝蜜| 日韩电影久久久被窝网| 大香伊人久久精品一区二区| 无码国内精品久久人妻麻豆按摩| 亚洲精品tv久久久久| 中文字幕乱码人妻无码久久| 久久w5ww成w人免费| 久久综合狠狠综合久久激情 | 国产免费久久久久久无码| 久久男人中文字幕资源站| 久久久久久伊人高潮影院| 午夜精品久久久久久久久| 国产一级做a爰片久久毛片| 大美女久久久久久j久久| 性欧美大战久久久久久久| 亚洲精品无码久久千人斩| 久久久久综合网久久| 亚洲国产成人乱码精品女人久久久不卡| 蜜桃麻豆WWW久久囤产精品| 久久国产乱子伦免费精品| 精品久久久久久国产牛牛app| 精品久久久久成人码免费动漫| 国内精品久久久久影院优| 欧美久久一级内射wwwwww.|