P1074 target shape Sudoku dfs + pretreatment

Keywords: PHP

https://www.luogu.org/problemnew/show/P1074

Obviously, it's dfs, and there's no pruning and memorization, but preprocessing is troublesome

I use three two-dimensional arrays to store the state: visx[x][i] represents whether row x is selected or not, visy[y][i] represents whether column y is selected or not, visg[g][i] represents whether the ninth house G is selected or not

When traversing, it is found that VISX [x] [i] = = 0 & & Visy [y] [i] = = 0 & & visg [g] [i] = = 0, indicating that I can go down dfs without being selected

As for the order of traversal, when we play Sudoku, we all know that we must start from the place with more known points

For example, the first line: 7 0 0 9 0 0 0 0 1 has 6 unknown locations

Line 9: 0 8 0 5 0 4 0 1 2 only 4 positions are unknown, so we must consider line 9 first

So just sort the rows and adjust the traversal order

However, sorting leads to a problem that we don't know the first row after sorting is the first row. To solve this problem, we can use a structure to store several unknown positions of each row:

typedef struct
{
    int nums=0;  //Number of unknown locations
    int x;    //Row number
}node;

Finally, we need to maintain a one-dimensional array to hold the modified traversal sequence (of course, two-dimensional can also be used)

At the end of last, the maximum value should be updated every time a group of Sudoku solutions are found

See the code:

#include<bits/stdc++.h>

using namespace std;

typedef struct
{
    int nums=0;
    int x;
}node;
node e[15];

int m[15][15],anss,u,visx[15][15],visy[15][15],visg[15][15],q[100],pre,flag;
int s[11][11]={0,0,0,0,0,0,0,0,0,0,0,           //It's lazy to save the scores in each position and type directly
               0,6,6,6,6,6,6,6,6,6,0,
               0,6,7,7,7,7,7,7,7,6,0,
               0,6,7,8,8,8,8,8,7,6,0,
               0,6,7,8,9,9,9,8,7,6,0,
               0,6,7,8,9,10,9,8,7,6,0,
               0,6,7,8,9,9,9,8,7,6,0,
               0,6,7,8,8,8,8,8,7,6,0,
               0,6,7,7,7,7,7,7,7,6,0,
               0,6,6,6,6,6,6,6,6,6,0,
               0,0,0,0,0,0,0,0,0,0,0};


bool cmp(node a,node b)
{
    return a.nums<b.nums;
}

void dfs(int t)
{
    int i,j;
    if(t==u+1)
    {
        flag=1;
        int p=0;
        for(i=1;i<=9;i++)
        for(j=1;j<=9;j++)
        p+=m[i][j]*s[i][j];
        anss=max(anss,p);   //Update Max
        return;
    }
    int x=(q[t]-1)/9+1;
    int y=q[t]-(x-1)*9;
    int g=((x-1)/3)*3+(y-1)/3+1;
    for(i=1;i<=9;i++)
    {
        if(visx[x][i]==0&&visy[y][i]==0&&visg[g][i]==0)
        {
            visx[x][i]=1;
            visy[y][i]=1;
            visg[g][i]=1;
            m[x][y]=i;
            dfs(t+1);
            visx[x][i]=0;
            visy[y][i]=0;
            visg[g][i]=0;
        } 
    }
}


int main()
{
    int i,j;
    for(i=1;i<=9;i++)
    e[i].x=i;
    for(i=1;i<=9;i++)
    for(j=1;j<=9;j++)
    {
        scanf("%d",&m[i][j]);
        if(m[i][j]==0)
        e[i].nums++;
        else
        {
            pre+=m[i][j]*s[i][j];
            visx[i][m[i][j]]=1;
            visy[j][m[i][j]]=1;
            int g=((i-1)/3)*3+(j-1)/3+1;   //Calculate which nine palace grid the current point belongs to
            visg[g][m[i][j]]=1;  
        }
    }
    sort(e+1,e+10,cmp);
    for(i=1;i<=9;i++)
    for(j=1;j<=9;j++)
    {
        if(m[e[i].x][j]==0)
        {
            int nums=(e[i].x-1)*9+j;  //If the current position is unknown, put it in the sequence to be traversed
            q[++u]=nums;  //u How many unknown points are recorded
        }
    }
    dfs(1);
    if(flag==0)  //If there is no solution
    {
        cout<<-1<<endl;
        return 0;
    }
    cout<<anss<<endl;

} 

Posted by pradeep79 on Sun, 03 Nov 2019 13:38:01 -0800