两种dlx解法比较 以及靶形数独

原链接1:http://blog.sina.com.cn/s/blog_51cea4040100gxn1.html  这女娃子改变我对女性的看法      第一个代码和第三个第四个代码(靶形数独)来源于此链接。

原链接2:http://yzmduncan.iteye.com/blog/1151695

本文第一个代码建舞池既节省时间重要的的是耗时也少。建舞池耗时在0-1ms,对于大量测试来说正满足额外开销小的要求。解题时间两代码相差无几,是因为数组是随机存取,如换为链表作数据结构,第一个代码耗时少。第一个代码先把题目中已填的数做预处理减少的耗时不好统计,因为整个解题时间也就3ms。

DLX比一般DFS快的理由:

 1:增加了行,列,宫中各九个候选数一共81*3=243个检测量,不但囊括了显隐唯一数技巧,还使探索指标增多。

 2:删除修复,同行,列,宫候选数时有条不紊,remove和resume是绝配不需要另外的空间和时间。


#include<cstdlib>
#include<iostream>
#include<time.h>
using namespace std;
const int maxr=9*9*9+10;
const int maxc=9*9*4+10;
int L[maxc+maxr*5],R[maxc+maxr*5],U[maxc+maxr*5],D[maxc+maxr*5];
int S[maxc];
int nRow[maxc+maxr*5];
int nCol[maxc+maxr*5];
int head[10][10][10];
int outcome[59],o_sub;
int cnt;
int map[10][10]={0,0,0,0,0,0,0,0,0,0,
              0,8,0,0,0,0,0,0,0,0,
     0,0,0,3,6,0,0,0,0,0,
     0,0,7,0,0,9,0,2,0,0,
     0,0,5,0,0,0,7,0,0,0,
     0,0,0,0,0,4,5,7,0,0,
     0,0,0,0,1,0,0,0,3,0,
     0,0,0,1,0,0,0,0,6,8,
     0,0,0,8,5,0,0,0,1,0,
     0,0,9,0,0,0,0,4,0,0};

bool init();
int subgrid(int,int);
void Ins_node(int,int);
void Remove(int);
void Resume(int);
bool dfs(int);
void print();
int test();
bool fun(int a[10]);


int subgrid(int i,int j)
{
    i--; j--;
    return (i/3)*3+(j/3+1);

    if (i<=3 && j<=3) return 1;
    if (i<=3 && j<=6) return 2;
    if (i<=3 && j<=9) return 3;
    if (i<=6 && j<=3) return 4;
    if (i<=6 && j<=6) return 5;
    if (i<=6 && j<=9) return 6;
    if (i<=9 && j<=3) return 7;
    if (i<=9 && j<=6) return 8;
    if (i<=9 && j<=9) return 9;
}
void Ins_node(int c,int cnt)
{
    U[D[c]]=cnt;
    D[cnt]=D[c];
    U[cnt]=c;
    D[c]=cnt;
    S[c]++;
    nCol[cnt]=c;
}
void Remove(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[nCol[j]]--;
        }
}
void Resume(int c)
{
    for (int i=U[c];i!=c;i=U[i])
        for (int j=L[i];j!=i;j=L[j])
        {
            U[D[j]]=D[U[j]]=j;
            S[nCol[j]]++;
        }
    L[R[c]]=R[L[c]]=c;
}
bool dfs(int k)
{
    if (k>81) return true;

    int c,minnum=INT_MAX;
    for (int i=R[0];i!=0;i=R[i])
    {
       // if (!S[i]) return false;
        if (S[i]<minnum)
        {
            minnum=S[i];
            c=i;
        }
    }

    Remove(c);
 outcome[o_sub++]=c;
    for (int i=D[c];i!=c;i=D[i])
    {
        int tmp=nRow[i];
        map[tmp/100][(tmp/10)%10]=tmp%10;
        for (int j=R[i];j!=i;j=R[j])
            Remove(nCol[j]);
        if (dfs(k+1)) return true;
        for (int j=L[i];j!=i;j=L[j])
            Resume(nCol[j]);
    }
    Resume(c);
 o_sub--;
    return false;
}
void print()
{
 for(int i=1;i<=9;i++)
 {
  if((i-1)%3==0) printf("\n");
  for(int j=1;j<=9;j++)
   if((j-1)%3==0) {  printf(" "); printf("%d ",map[i][j]);}
   else   printf("%d ",map[i][j]);
        printf("\n");
 }
}
int test()
  {
 int sum=0,i,j,aray[10];
 for(int i=1;i<=9;i++)
  {
      sum=0;
   for(int j=1;j<=9;j++)
      { sum+=map[i][j];  aray[j]=map[i][j];}
   if(sum!=45) {cout<<"wrong"<<endl;   return 0;}
   if(!fun(aray))  return 0;
     }
 for( j=1;j<=9;j++)
  {
      sum=0;
   for(i=1;i<=9;i++)
         { sum+=map[i][j];  aray[i]=map[i][j];}
   if(sum!=45)  {cout<<"wrong"<<endl;   return 0;}
   if(!fun(aray))  return 0;
     }
 for(int k=1;k<=9;k++)
 {
  sum=0;
  int row=(k-1)/3*3+1,col=(k-1)%3*3+1,sub=1;
  for(i=row;i<=row+2;i++)
   for(j=col;j<=col+2;j++)
    { sum+=map[i][j];  aray[sub++]=map[i][j];}
        if(sum!=45)  {cout<<"wrong"<<endl;   return 0;}
  if(!fun(aray))  return 0;
 }
 return 1;
  }
bool  fun( int a[10])
{
 int i,j;
 for(i=1;i<=8;i++)
 {
  if(*(a+i)==0)  continue;
  for(j=i+1;j<=9;j++)
   if(*(a+i)==*(a+j)) return (false);
 }
 return (true);
}

int main()
{
    freopen("d:\\c++\\数独12\\question\\question475.txt","w",stdout);
 int op=1;
 srand(time(0));
 long time1,time2,time3=0;
 
  time1=clock();
        for (int i=0;i<=81*4;i++)
        {
            S[i]=0;
            L[i]=i-1; R[i]=i+1;
            U[i]=D[i]=i;
            nCol[i]=0;
        }
        L[0]=81*4; R[81*4]=0;

        cnt=81*4;
        for (int i=1;i<=9;i++)
            for (int j=1;j<=9;j++)
            {
                if (map[i][j])
                {
                    int k=map[i][j];
                    for (int u=1;u<=4;u++)
                    {
                        L[cnt+u]=cnt+u-1;
                        R[cnt+u]=cnt+u+1;
                        nRow[cnt+u]=100*i+10*j+k;
                    }
                    L[cnt+1]=cnt+4; R[cnt+4]=cnt+1;
                    head[i][j][k]=cnt+1;
                    Ins_node((i-1)*9+j,cnt+1);
                    Ins_node(81+(i-1)*9+k,cnt+2);
                    Ins_node(81*2+(j-1)*9+k,cnt+3);
                    Ins_node(81*3+(subgrid(i,j)-1)*9+k,cnt+4);
                    cnt+=4;
                }
                else
                    for (int k=1;k<=9;k++)
                    {
                        for (int u=1;u<=4;u++)
                        {
                            L[cnt+u]=cnt+u-1;
                            R[cnt+u]=cnt+u+1;
                            nRow[cnt+u]=100*i+10*j+k;
                        }
                        L[cnt+1]=cnt+4; R[cnt+4]=cnt+1;
                        head[i][j][k]=cnt+1;
                        Ins_node((i-1)*9+j,cnt+1);
                        Ins_node(81+(i-1)*9+k,cnt+2);
                        Ins_node(81*2+(j-1)*9+k,cnt+3);
                        Ins_node(81*3+(subgrid(i,j)-1)*9+k,cnt+4);
                        cnt+=4;
                    }
            }
        time2=clock(); 
        int k=0;
        for (int i=1;i<=9;i++)
            for (int j=1;j<=9;j++)
                if (map[i][j])
                {
                    k++;
                    Remove(nCol[head[i][j][map[i][j]]]);
                    for (int u=R[head[i][j][map[i][j]]];u!=head[i][j][map[i][j]];u=R[u])
                        Remove(nCol[u]);
                }
        dfs(k+1);
  time3=clock();
  if(test()) print();
  else cout<<op<<endl;
 
 cout<<"建舞池用时"<<time2-time1<<"ms"<<"解题用时"<<time3-time2<<"ms"<<endl;
 
}

 

 

 

 

 

 

 

 

 

#include <iostream>  
#include<time.h>
using namespace std;  
const int INF = 0x7fffffff;  
const int NN = 350;  
const int MM = 750;  
int n,m;    //列,行  
int cntc[NN];  
int L[NN*MM],R[NN*MM],U[NN*MM],D[NN*MM];  
int C[NN*MM];  
int head;  
int mx[MM][NN];  
int O[MM],idx;  
int ans[10][10];
int map[10][10]={0,0,0,0,0,0,0,0,0,0,
              0,8,0,0,0,0,0,0,0,0,
     0,0,0,3,6,0,0,0,0,0,
     0,0,7,0,0,9,0,2,0,0,
     0,0,5,0,0,0,7,0,0,0,
     0,0,0,0,0,4,5,7,0,0,
     0,0,0,0,1,0,0,0,3,0,
     0,0,0,1,0,0,0,0,6,8,
     0,0,0,8,5,0,0,0,1,0,
     0,0,9,0,0,0,0,4,0,0};
 
//删除列及其相应的行  
void remove(int c)  
{  
    int i,j;  
    L[R[c]] = L[c];  
    R[L[c]] = R[c];  
    for(i = D[c]; i != c; i = D[i])  
    {  
        for(j = R[i]; j != i; j = R[j])  
        {  
            U[D[j]] = U[j];  
            D[U[j]] = D[j];  
            cntc[C[j]]--;  
        }  
    }  
}  
//恢复列及其相应的行  
void resume(int c)  
{  
    int i,j;  
    R[L[c]] = c;  
    L[R[c]] = c;  
    for(i = D[c]; i != c; i = D[i])  
    {  
        for(j = R[i]; j != i; j = R[j])  
        {  
            U[D[j]] = j;  
            D[U[j]] = j;  
            cntc[C[j]]++;  
        }  
    }  
}  
bool dfs()  
{  
    int i,j,c;  
    if(R[head] == head)  
        return true;  
    int min = INF;  
    for(i = R[head]; i != head; i = R[i])  
    {  
        if(cntc[i] < min)  
        {  
            min = cntc[i];  
            c = i;  
        }  
    }  
    remove(c);  
    for(i = D[c]; i != c; i = D[i])  
    {  
        //i是某点的序号,将该点所在行的行号保存  
        O[idx++] = (i-1)/n;  
        for(j = R[i]; j != i; j = R[j])  
            remove(C[j]);  
        if(dfs())  
            return true;  
        for(j = L[i]; j != i; j = L[j])  
            resume(C[j]);  
        idx--;  
    }  
    resume(c);  
    return false;  
}  
bool build()  
{  
    int i,j,now,pre,first;  
    idx = head = 0;  
    for(i = 0; i < n; i++)  
    {  
        R[i] = i+1;  
        L[i+1] = i;  
    }  
    R[n] = 0;  
    L[0] = n;  
    //列双向链表  
    for(j = 1; j <= n; j++)  
    {  
        pre = j;  
        cntc[j] = 0;  
        for(i = 1; i <= m; i++)  
        {  
            if(mx[i][j])  
            {  
                cntc[j]++;  
                now = i*n+j;  
                C[now] = j;  
                D[pre] = now;  
                U[now] = pre;  
                pre = now;  
            }  
        }  
        U[j] = pre;  
        D[pre] = j;  
        if(cntc[j] == 0)  
            return false;  
    }  
    //行双向链表  
    for(i = 1; i <= m; i++)  
    {  
        pre = first = -1;  
        for(j = 1; j <= n; j++)  
        {  
            if(mx[i][j])  
            {  
                now = i*n+j;  
                if(pre == -1)  
                    first = now;  
                else 
                {  
                    R[pre] = now;  
                    L[now] = pre;  
                }  
                pre = now;  
            }  
        }  
        if(first != -1)  
        {  
            R[pre] = first;  
            L[first] = pre;  
        }  
    }  
    return true;  
}  
void print()  
{  
    int i,j;  
    int x,y,k;  
    for(i = 0; i < idx; i++)  
    {  
        int r = O[i];  
        k = r%9;  
        if(k==0) k = 9;  
        int num = (r - k)/9 + 1;  
        y = num%9;  
        if(y == 0) y = 9;  
        x = (num-y)/9 + 1;  
        ans[x][y] = k;  
    }  
    if(idx == 0)  
        printf("impossible\n");  
    else 
    {  
        for(i = 1; i <= 9; i++)  
        {  
            for(j = 1; j <= 9; j++)  
                printf("%d",ans[i][j]);  
            printf("\n");  
        }  
    }  
}

int main()  
{  
    int i,j,k;  
 long time1,time2,time3;
 char s[10][10];
  
  for(int i=1;i<=9;i++)
   for(int j=1;j<=9;j++)
    if(map[i][j])  s[i][j]=48+map[i][j];
    else   s[i][j]='?';
        memset(mx,0,sizeof(mx));
  time1=clock();
        for(i = 1; i <= 9; i++)  
        {  
            for(j = 1; j <= 9; j++)  
             {  
                int t = (i-1)*9 + j;  
                if(s[i][j] == '?')  
                {  
                    for(k = 1; k <= 9; k++)  
                    {  
                        mx[9*(t-1)+k][t] = 1;               //81grid 每个小格只能放一个数字  
                        mx[9*(t-1)+k][81+(i-1)*9+k] = 1;    //9row 每行数字k只能出现一次  
                        mx[9*(t-1)+k][162+(j-1)*9+k] = 1;   //9col  每列数字k只能出现一次  
                        mx[9*(t-1)+k][243+((i-1)/3*3+(j+2)/3-1)*9+k] = 1;   //subgrid 每个3*3格子数字k只能出现一次  
                    }  
                }  
                else 
                {  
                    k = s[i][j] - '0';  
                    mx[9*(t-1)+k][t] = 1;               //81grid  
                    mx[9*(t-1)+k][81+(i-1)*9+k] = 1;    //9row  
                    mx[9*(t-1)+k][162+(j-1)*9+k] = 1;   //9col  
                    mx[9*(t-1)+k][243+((i-1)/3*3+(j+2)/3-1)*9+k] = 1;   //subgrid  
                }  
            }  
        }  
        n = 324;  
        m = 729;  
        build();
  time2=clock();
        dfs();
  time3=clock();
        print();
  
 cout<<"建舞池用时"<<time2-time1<<"ms"<<"解题用时"<<time3-time2<<"ms"<<endl;
 getchar(); getchar();
    return 0;  

 

 

 

 

 

 

 

 

 

 

#include<iostream>
using namespace std;
const int maxr=9*9*9+10;
const int maxc=9*9*4+10;
int L[maxc+maxr*5],R[maxc+maxr*5],U[maxc+maxr*5],D[maxc+maxr*5];
int S[maxc];
int nRow[maxc+maxr*5];
int nCol[maxc+maxr*5];
int head[10][10][10];
int cnt;
int map[10][10];
int data1[9][9]=
 {7,0,0,9,0,0,0,0,1,
  1,0,0,0,0,5,9,0,0,
  0,0,0,2,0,0,0,8,0,
  0,0,5,0,2,0,0,0,3,
  0,0,0,0,0,0,6,4,8,
  4,1,3,0,0,0,0,0,0,
  0,0,7,0,0,2,0,9,0,
  2,0,1,0,6,0,8,0,4,
  0,8,0,5,0,4,0,1,2};
int data2[9][9]=
 {0,0,0,7,0,2,4,5,3,
  9,0,0,0,0,8,0,0,0,
  7,4,0,0,0,5,0,1,0,
  1,9,5,0,8,0,0,0,0,
  0,7,0,0,0,0,0,2,5,
  0,3,0,5,7,9,1,0,8,
  0,0,0,6,0,1,0,0,0,
  0,6,0,9,0,0,0,0,1,
  0,0,0,0,0,0,0,0,6};
int best=-1,SCORE=0;
int score[10][10]=
{
 {0,0,0,0,0,0,0,0,0,0},
 {0,6,6,6,6,6,6,6,6,6},
 {0,6,7,7,7,7,7,7,7,6},
 {0,6,7,8,8,8,8,8,7,6},
 {0,6,7,8,9,9,9,8,7,6},
 {0,6,7,8,9,10,9,8,7,6},
 {0,6,7,8,9,9,9,8,7,6},
 {0,6,7,8,8,8,8,8,7,6},
 {0,6,7,7,7,7,7,7,7,6},
 {0,6,6,6,6,6,6,6,6,6}
};


int subgrid(int i,int j)
{
    i--; j--;
    return (i/3)*3+(j/3+1);
}
void Ins_node(int c,int cnt)
{
    U[D[c]]=cnt;
    D[cnt]=D[c];
    U[cnt]=c;
    D[c]=cnt;
    S[c]++;
    nCol[cnt]=c;
}
void Remove(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[nCol[j]]--;
        }
}
void Resume(int c)
{
    for (int i=U[c];i!=c;i=U[i])
        for (int j=L[i];j!=i;j=L[j])
        {
            U[D[j]]=D[U[j]]=j;
            S[nCol[j]]++;
        }
    L[R[c]]=R[L[c]]=c;
}
void dfs(int k)
{
    if (k>81)
    {
        cout<<SCORE<<endl;
  if (SCORE>best) best=SCORE;
        return;
    }

    int c,minnum=INT_MAX;
    for (int i=R[0];i!=0;i=R[i])
    {
        if (!S[i]) return;
        if (S[i]<minnum)
        {
            minnum=S[i];
            c=i;
        }
    }

    Remove(c);
    for (int i=D[c];i!=c;i=D[i])
    {
        int tmp=nRow[i];
        SCORE=SCORE+(tmp%10)*(score[tmp/100][(tmp/10)%10]);
        for (int j=R[i];j!=i;j=R[j])
            Remove(nCol[j]);
        dfs(k+1);
        SCORE=SCORE-(tmp%10)*(score[tmp/100][(tmp/10)%10]);
        for (int j=L[i];j!=i;j=L[j])
            Resume(nCol[j]);
    }
    Resume(c);
}

 

int main()
{
        freopen("d:\\c++\\数独12\\question\\question474.txt","w",stdout);
        for(int i=1;i<=9;i++)
   for(int j=1;j<=9;j++)
    map[i][j]=data1[i-1][j-1];
        for (int i=0;i<=81*4;i++)
        {
            S[i]=0;
            L[i]=i-1; R[i]=i+1;
            U[i]=D[i]=i;
            nCol[i]=0;
        }
        L[0]=81*4; R[81*4]=0;
        cnt=81*4;
        for (int i=1;i<=9;i++)
            for (int j=1;j<=9;j++)
            {
                if (map[i][j])
                {
                    int k=map[i][j];
                    for (int u=1;u<=4;u++)
                    {
                        L[cnt+u]=cnt+u-1;
                        R[cnt+u]=cnt+u+1;
                        nRow[cnt+u]=100*i+10*j+k;
                    }
                    L[cnt+1]=cnt+4; R[cnt+4]=cnt+1;
                    head[i][j][k]=cnt+1;
                    Ins_node((i-1)*9+j,cnt+1);
                    Ins_node(81+(i-1)*9+k,cnt+2);
                    Ins_node(81*2+(j-1)*9+k,cnt+3);
                    Ins_node(81*3+(subgrid(i,j)-1)*9+k,cnt+4);
                    cnt+=4;
                }
                else
                    for (int k=1;k<=9;k++)
                    {
                        for (int u=1;u<=4;u++)
                        {
                            L[cnt+u]=cnt+u-1;
                            R[cnt+u]=cnt+u+1;
                            nRow[cnt+u]=100*i+10*j+k;
                        }
                        L[cnt+1]=cnt+4; R[cnt+4]=cnt+1;
                        head[i][j][k]=cnt+1;
                        Ins_node((i-1)*9+j,cnt+1);
                        Ins_node(81+(i-1)*9+k,cnt+2);
                        Ins_node(81*2+(j-1)*9+k,cnt+3);
                        Ins_node(81*3+(subgrid(i,j)-1)*9+k,cnt+4);
                        cnt+=4;
                    }
            }
        int k=0;
        for (int i=1;i<=9;i++)
            for (int j=1;j<=9;j++)
                if (map[i][j])
                {
                    k++;
                    SCORE+=(map[i][j])*score[i][j];
                    Remove(nCol[head[i][j][map[i][j]]]);
                    for (int u=R[head[i][j][map[i][j]]];u!=head[i][j][map[i][j]];u=R[u])
                        Remove(nCol[u]);
                }
        dfs(k+1);
        printf("%d\n",best);
        fclose(stdout);
        return 0;
}

 

 

 

 

 

 

//http://blog.csdn.net/nhczp/article/details/1498868 这个链接产生多解的题目 并输出原始终盘(用来挖洞),以及题目,还有这个题目的一切解题结果
//http://blog.sina.com.cn/s/blog_51cea4040100gxn1.html 这个链接解靶形数独并输出最好得分
//输出到屏幕终端的是有都少个解法   输出到一个文件的是原始终盘(用来挖洞),以及题目,还有这个题目的一切解题结果, 输出到另一个文件的结果是每一个解题结果对应的分数最后输出最大分数
//速度真快,第一种解题用的是dfs第二种解题用的是dlx(解靶形数独) 两种都快啊 
//如果有靶形数独题目,还可以直接输入,data1,和data2就是两个靶形数独题目,在main函数里只需要屏蔽一些代码启用另一些代码就可测试特定的靶形数独题目
#include "time.h"
#include<cstdlib>
#include<iostream>
#include<fstream>
using namespace std;


ofstream out_stream;
 enum{ANY=0,ALL=1};
int map_exchange[9][9];
 int smod;
 int solves;

 

const int maxr=9*9*9+10;
const int maxc=9*9*4+10;
int L[maxc+maxr*5],R[maxc+maxr*5],U[maxc+maxr*5],D[maxc+maxr*5];
int S[maxc];
int nRow[maxc+maxr*5];
int nCol[maxc+maxr*5];
int head[10][10][10];
int cnt;
int map[10][10];
int data1[9][9]=
 {7,0,0,9,0,0,0,0,1,
  1,0,0,0,0,5,9,0,0,
  0,0,0,2,0,0,0,8,0,
  0,0,5,0,2,0,0,0,3,
  0,0,0,0,0,0,6,4,8,
  4,1,3,0,0,0,0,0,0,
  0,0,7,0,0,2,0,9,0,
  2,0,1,0,6,0,8,0,4,
  0,8,0,5,0,4,0,1,2};
int data2[9][9]=
 {0,0,0,7,0,2,4,5,3,
  9,0,0,0,0,8,0,0,0,
  7,4,0,0,0,5,0,1,0,
  1,9,5,0,8,0,0,0,0,
  0,7,0,0,0,0,0,2,5,
  0,3,0,5,7,9,1,0,8,
  0,0,0,6,0,1,0,0,0,
  0,6,0,9,0,0,0,0,1,
  0,0,0,0,0,0,0,0,6};
int best=-1,SCORE=0;
int score[10][10]=
{
 {0,0,0,0,0,0,0,0,0,0},
 {0,6,6,6,6,6,6,6,6,6},
 {0,6,7,7,7,7,7,7,7,6},
 {0,6,7,8,8,8,8,8,7,6},
 {0,6,7,8,9,9,9,8,7,6},
 {0,6,7,8,9,10,9,8,7,6},
 {0,6,7,8,9,9,9,8,7,6},
 {0,6,7,8,8,8,8,8,7,6},
 {0,6,7,7,7,7,7,7,7,6},
 {0,6,6,6,6,6,6,6,6,6}
};


 int check(int,int,int*);
 void dfs();
 void CSudoku(int n=40);// 随机生成数独,n越大越难
 void display();
 void print_all();
 int resolve(int mod=ALL);// 解数独


int subgrid(int,int);
void Ins_node(int,int);
void Remove(int);
void Resume(int);
void dfs(int);


void CSudoku(int n)
{
 int i,j;
 srand(time(0));
 do
 {
  for(i=0;i<9;++i)
  {
   for(j=0;j<9;++j)
    map_exchange[i][j]=0;
   j=rand()%9;
   map_exchange[i][j]=i+1;
  }
 }
 while(!resolve(ANY));

 // 挖窟窿
 for(int k=0;k<n;)
 {
  i=rand()%81;
  j=i%9;
  i=i/9;
  if(map_exchange[i][j]>0)
  {
   map_exchange[i][j]=0;
   ++k;
  }

 }
}
void display()
{
 out_stream<<"┏━┯━┯━┳━┯━┯━┳━┯━┯━┓"<<endl;

 for(int i=0;i<9;++i)
 {
  for(int j=0;j<9;++j)
  {
   if(map_exchange[i][j]>0)
   {
    if(j%3==0)
     out_stream<<"┃ "<<map_exchange[i][j];
    else
     out_stream<<"│ "<<map_exchange[i][j];
    
   }
   else
   {
    if(j%3==0)
     out_stream<<"┃  ";
    else
     out_stream<<"│  ";
   }
  }
  out_stream<<"┃"<<endl;
  if (i!=8)
  {
   if((i+1)%3==0)
    out_stream<<"┣━┿━┿━╋━┿━┿━╋━┿━┿━┫"<<endl;
   else
    out_stream<<"┠─┼─┼─╂─┼─┼─╂─┼─┼─┨"<<endl;
  }  }
 out_stream<<"┗━┷━┷━┻━┷━┷━┻━┷━┷━┛"<<endl;
}
void  print_all()

 out_stream<<"print storage"<<endl;
   for(int i=1;i<=9;i++)
     {
    for(int j=1;j<=9;j++)
     {
   out_stream<<map_exchange[i-1][j-1]<<" ";
     if(j%3==0) out_stream<<"   ";
     }   
    out_stream<<endl;
    if(i%3==0)  out_stream<<endl;
     }
   out_stream<<endl<<endl;
}
int resolve(int mod)
{
 smod=mod;
 if(mod==ALL)
 {
  solves=0;
  dfs();
  return solves;
 }
 else if(mod==ANY)
 {
  try
  {
   dfs();
   return 0;
  }
  catch(int)
  {
   return 1;
  }
 }
 return 0;
}
int check(int y,int x,int *mark)  //求probable[y][x]
{
 int i,j,is,js,count=0;
 for(i=1;i<=9;++i)
  mark[i]=0;
 for(i=0;i<9;++i)
  mark[map_exchange[y][i]]=1;
 for(i=0;i<9;++i)
  mark[map_exchange[i][x]]=1;
 is=y/3*3;
 js=x/3*3;
 for(i=0;i<3;++i)
 {
  for(j=0;j<3;++j)
   mark[map_exchange[is+i][js+j]]=1;
 }
 for(i=1;i<=9;++i)
  if(mark[i]==0)
   count++;
 return count;
}
void dfs()
{
 int i,j,im=-1,jm,min=10;
 int mark[10];
 for(i=0;i<9;++i)
 {
  for(j=0;j<9;++j)
  {
   if(map_exchange[i][j])
    continue;
   int c=check(i,j,mark);
   if(c==0)
    return;
   if(c<min)
   {
    im=i;
    jm=j;
    min=c;
   }
  }
 }
 if(im==-1)
 {
  if(smod==ALL)
  {
   printf("No. %d",++solves);
   printf("\n");
   display();
   return;
  }
  else if(smod==ANY)
  {
      display();
   throw(1);
  }
 }
 check(im,jm,mark);
 for(i=1;i<=9;++i)
 {
  if(mark[i]==0)
  {
   map_exchange[im][jm]=i;
   dfs();
  }
 }
 map_exchange[im][jm]=0;
}

 

 

int subgrid(int i,int j)
{
    i--; j--;
    return (i/3)*3+(j/3+1);
}
void Ins_node(int c,int cnt)
{
    U[D[c]]=cnt;
    D[cnt]=D[c];
    U[cnt]=c;
    D[c]=cnt;
    S[c]++;
    nCol[cnt]=c;
}
void Remove(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[nCol[j]]--;
        }
}
void Resume(int c)
{
    for (int i=U[c];i!=c;i=U[i])
        for (int j=L[i];j!=i;j=L[j])
        {
            U[D[j]]=D[U[j]]=j;
            S[nCol[j]]++;
        }
    L[R[c]]=R[L[c]]=c;
}
void dfs(int k)
{
    if (k>81)
    {
        cout<<SCORE<<endl;
  if (SCORE>best) best=SCORE;
        return;
    }

    int c,minnum=INT_MAX;
    for (int i=R[0];i!=0;i=R[i])
    {
        if (!S[i]) return;
        if (S[i]<minnum)
        {
            minnum=S[i];
            c=i;
        }
    }

    Remove(c);
    for (int i=D[c];i!=c;i=D[i])
    {
        int tmp=nRow[i];
        SCORE=SCORE+(tmp%10)*(score[tmp/100][(tmp/10)%10]);
        for (int j=R[i];j!=i;j=R[j])
            Remove(nCol[j]);
        dfs(k+1);
        SCORE=SCORE-(tmp%10)*(score[tmp/100][(tmp/10)%10]);
        for (int j=L[i];j!=i;j=L[j])
            Resume(nCol[j]);
    }
    Resume(c);
}

 

int main()
{
         int blanks;
         out_stream.open("d:\\c++\\数独12\\question\\question474.txt");
   cout<<"请输入blanks值"<<endl;
         cin>>blanks;
         CSudoku (blanks);
   for(int i=1;i<=9;i++)
    for(int j=1;j<=9;j++)
     map[i][j]=map_exchange[i-1][j-1];
         display();
         resolve(ALL);
         out_stream.close();

     freopen("d:\\c++\\数独12\\question\\question475.txt","w",stdout);
        /*for(int i=1;i<=9;i++)
   for(int j=1;j<=9;j++)
    map[i][j]=data1[i-1][j-1];*/
        for (int i=0;i<=81*4;i++)
        {
            S[i]=0;
            L[i]=i-1; R[i]=i+1;
            U[i]=D[i]=i;
            nCol[i]=0;
        }
        L[0]=81*4; R[81*4]=0;
        cnt=81*4;
        for (int i=1;i<=9;i++)
            for (int j=1;j<=9;j++)
            {
                if (map[i][j])
                {
                    int k=map[i][j];
                    for (int u=1;u<=4;u++)
                    {
                        L[cnt+u]=cnt+u-1;
                        R[cnt+u]=cnt+u+1;
                        nRow[cnt+u]=100*i+10*j+k;
                    }
                    L[cnt+1]=cnt+4; R[cnt+4]=cnt+1;
                    head[i][j][k]=cnt+1;
                    Ins_node((i-1)*9+j,cnt+1);
                    Ins_node(81+(i-1)*9+k,cnt+2);
                    Ins_node(81*2+(j-1)*9+k,cnt+3);
                    Ins_node(81*3+(subgrid(i,j)-1)*9+k,cnt+4);
                    cnt+=4;
                }
                else
                    for (int k=1;k<=9;k++)
                    {
                        for (int u=1;u<=4;u++)
                        {
                            L[cnt+u]=cnt+u-1;
                            R[cnt+u]=cnt+u+1;
                            nRow[cnt+u]=100*i+10*j+k;
                        }
                        L[cnt+1]=cnt+4; R[cnt+4]=cnt+1;
                        head[i][j][k]=cnt+1;
                        Ins_node((i-1)*9+j,cnt+1);
                        Ins_node(81+(i-1)*9+k,cnt+2);
                        Ins_node(81*2+(j-1)*9+k,cnt+3);
                        Ins_node(81*3+(subgrid(i,j)-1)*9+k,cnt+4);
                        cnt+=4;
                    }
            }
        int k=0;
        for (int i=1;i<=9;i++)
            for (int j=1;j<=9;j++)
                if (map[i][j])
                {
                    k++;
                    SCORE+=(map[i][j])*score[i][j];
                    Remove(nCol[head[i][j][map[i][j]]]);
                    for (int u=R[head[i][j][map[i][j]]];u!=head[i][j][map[i][j]];u=R[u])
                        Remove(nCol[u]);
                }
        dfs(k+1);
        printf("%d\n",best);
        fclose(stdout);
        system("pause");
}

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值