100722A

这道题抄了答案:

思路:旋转,其实只用旋转四次,因为在换行的过程中旋转其实是没有意义的,因为行列只不过转了个角度。然后主要的是行列的交换,这里我很头疼,写了个盲目搜索,当然wa掉了

问了问某位同志,是这样做的,很巧妙:其实这是一个全排列,一个三个数的全排列套了三个数的全排列,然后该怎么做呢?这里运用了一个巧妙的方法:range

range很巧妙,分两种情况:当我选完了三列时,这时我需要新的一列,那么我返回(0,8),意思是下一个列可以从(0,8)之间没用过的任选。第二呢,是我正在选三列中的一列,这时

我看看上一列我选的什么,这次我选的只能是(上一列设为x)[x/3*3,x/3*3+2]举个例子:(0,1,2) (3,4,5)(6,7,8)其实就是这三个块,他们每三个数必须绑在一起

然后我搜完了列之后搜行(搜行的时候我犯了个错误,对应残缺的数独下标没想清楚,debug了很长时间,下次应该想清楚)然后就是重复同样的过程,只不过要加上置换,

置换需要用一个额外的数组记录是那一列的时候替换的,因为会导致还原的时候不知道哪些要还原,然后就好了。

#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

typedef pair<int,int> pii;

string s;
int used_col[10],used_row[10],place[10];
int pos_row[10],pos_col[10],place_flag[10];
int b[10][10],c[10][10];

void init()
{
    memset(place_flag,-1,sizeof(place_flag));
    memset(place,-1,sizeof(place));
    memset(pos_row,-1,sizeof(pos_row));
    memset(pos_col,-1,sizeof(pos_col));
    memset(used_row,0,sizeof(used_row));
    memset(used_col,0,sizeof(used_col));    
}

pii get_range(int pos,int f)
{
    if(pos%3==0) return pii(0,8);
    int head=0;
    if(!f) head=pos_row[pos-1]/3*3;
    else head=pos_col[pos-1]/3*3;
    return pii(head,head+2);
}

void rotate()
{
    int a[10][10];memset(a,0,sizeof(a));
    for(int i=0;i<9;i++)
        for(int j=0;j<9;j++) a[9-j-1][i]=b[i][j];
    for(int i=0;i<9;i++) 
        for(int j=0;j<9;j++) b[i][j]=a[i][j];    
}

bool go_col(int d)
{
    if(d==9) return true;
    pii range=get_range(d,1);
    for(int i=range.first;i<=range.second;i++) if(!used_col[i])
    {
        used_col[i]=1;
        pos_col[d]=i;
        bool flag=false;
        for(int j=0;j<9;j++)
        {
            int x=b[pos_row[j]][pos_col[d]],y=c[j][d];
            if(y==0) continue;
            if(place[x]!=-1&&place[x]!=y) {flag=true;break;}
            if(place[x]==-1)
            { 
                place[x]=y;
                place_flag[x]=d;
            }
        }
        if(!flag) if(go_col(d+1)) return true;    
        for(int j=0;j<9;j++) 
        {
            int x=b[pos_row[j]][pos_col[d]];
            if(place_flag[x]==d) {place_flag[x]=-1;place[x]=-1;}
        }
        used_col[i]=0;
        pos_col[d]=-1;
    }        
    return false;
}

bool go_row(int d)//
{
    if(d==9) return go_col(0);
    pii range=get_range(d,0);
    for(int i=range.first;i<=range.second;i++) 
    {
        if(!used_row[i]) 
        {
            used_row[i]=1;
            pos_row[d]=i;
            if(go_row(d+1)) return true;
            used_row[i]=0;
            pos_row[d]=-1;
        }
    }    
    return false;
}

bool work()
{
    for(int i=0;i<4;i++)
    {
        init();
        rotate();
        if(go_row(0)) return true; 
    }
    return false;
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        for(int i=0;i<9;i++)
        {
            cin>>s;
            for(int j=0;j<9;j++)
            {
                b[i][j]=s[j]-'0';
            }
        }
        for(int i=0;i<9;i++)
        {
            cin>>s;
            for(int j=0;j<9;j++)
            {
                c[i][j]=s[j]-'0';
            }
        }
        if(work()) printf("Yes
"); else printf("No
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/19992147orz/p/6021040.html