code1174 靶形数独

Posted FuTaimeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了code1174 靶形数独相关的知识,希望对你有一定的参考价值。

主要是优化搜索顺序

从选择较少的点开始,可以大大提高效率

在search(x,y)找点的时候,对于一个空点(x y),设置一个评分score:

score=min{ 横线x上能填的数字个数,竖线y上...个数,所在大方块中...个数 }

选取score最小的点搜索

 

代码:

#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
const int N = 9;
const int Size = N+5;

int ans=-1;
int data[Size][Size];
bool a[Size][Size],b[Size][Size],c[Size][Size];//行 列 大方格 
int numA[Size],numB[Size],numC[Size];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int dic[Size][Size]={
    {0,0,0,0,0,0,0,0,0,0},
    {0,1,1,1,2,2,2,3,3,3},
    {0,1,1,1,2,2,2,3,3,3},
    {0,1,1,1,2,2,2,3,3,3},
    {0,4,4,4,5,5,5,6,6,6},
    {0,4,4,4,5,5,5,6,6,6},
    {0,4,4,4,5,5,5,6,6,6},
    {0,7,7,7,8,8,8,9,9,9},
    {0,7,7,7,8,8,8,9,9,9},
    {0,7,7,7,8,8,8,9,9,9}
};
int len[Size]={ 0,
    8,6,4,2,1
};

int getscore(){
    int ans=0;
    int x,y;
    for(int temp=1;temp<=N/2;temp++){
        x=y=temp;
        for(int k=0;k<4;k++){
            for(int i=1;i<=len[temp];i++){
                ans+=data[x][y]*(temp+5);
                x+=dx[k];y+=dy[k];
            }
        }
    }
    ans+=data[5][5]*10;
    return ans;
}

void search(int& x,int& y){
    x=y=0;
    int best=999999,score;
    for(int i=1;i<=N;i++){
        for(int j=1;j<=N;j++){
            if(data[i][j]==0){
                score=min(numA[i],numB[j]);
                score=min(score,numC[dic[i][j]]);
                if(score<best){
                    x=i;y=j;
                    best=score;
                }
            }
        }
    }
}

void dfs(){
    int x,y;
    search(x,y);
    if(x==0){
        ans=max(ans,getscore());
        //exit(0);
        return;
    }
    bool num[Size];
    memset(num,true,sizeof(num));
    int ff=dic[x][y];
    for(int k=1;k<=N;k++){
        if(a[x][k]==true||b[y][k]==true||c[ff][k]==true)
            num[k]=false;
    }
    for(int k=1;k<=N;k++){
        if(num[k]==true){
            data[x][y]=k;
            a[x][k]=true;b[y][k]=true;c[ff][k]=true;
            numA[x]--;numB[y]--;numC[ff]--;
            dfs();
            numA[x]++;numB[y]++;numC[ff]++;
            a[x][k]=false;b[y][k]=false;c[ff][k]=false;
            data[x][y]=0;
        }
    }
    return;
}

int main(){
    freopen("1174.in","r",stdin);
    for(int i=1;i<=9;i++)numA[i]=numB[i]=numC[i]=9;
    int x;
    for(int i=1;i<=N;i++){
        for(int j=1;j<=N;j++){
            cin>>x;
            if(x!=0){
                a[i][x]=true;numA[i]--;
                b[j][x]=true;numB[j]--;
                c[dic[i][j]][x]=true;numC[dic[i][j]]--;
            }
            data[i][j]=x;
        }
    }
    dfs(); 
    cout<<ans<<endl;
    
    fclose(stdin);
    return 0;
} 

 

以上是关于code1174 靶形数独的主要内容,如果未能解决你的问题,请参考以下文章

CODEVS 1174 靶形数独

[NOIP2009提高组]靶形数独

[NOIP2009] 靶形数独

NOIP2009靶形数独

[NOIP2009]靶形数独 题解

洛谷 P1074靶形数独