zoukankan      html  css  js  c++  java
  • P1074 靶形数独

    P1074 靶形数独

    dfs 优化搜索顺序

    我们可以想到一种方法,每次找可以填的数最少的格子进行dfs。

    离线 85pts

    在线 100pts

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct data{int x,y;};
    const int maxn=100; //由于未知原因,我的代码需要开10倍的数组不然会RE(???)
    int ans=-1,val[maxn][maxn],score[maxn][maxn],l[maxn],r[maxn]; //val,score:填入的数,和给出的分数 l,r:该行/列已填几个数
    bool use1[maxn][maxn],use2[maxn][maxn],use3[10][10][maxn],vis[maxn][maxn]; //use1,2,3:行、列、九宫格限制可填的数
    inline int blo(int &a) {return (a-1)/3+1;} //求所在块的编号
    inline data find(){ //在线找可填数最小的点
        int mxl=-1,mxr=-1,L,R;
        for(int i=1;i<=9;++i) if(l[i]>mxl&&l[i]<9) L=i,mxl=l[i];
        for(int i=1;i<=9;++i) if(r[i]>mxr&&!val[L][i]) R=i,mxr=r[i];
        return (data){L,R};
    }
    inline void dfs(int step,int tot,data node){
        if(step==81) {ans=ans>tot ? ans:tot; return ;}
        int x=node.x,y=node.y;
        for(int i=1;i<=9;++i){
            if(use1[x][i]||use2[y][i]||use3[blo(x)][blo(y)][i]) continue;
            val[x][y]=i;
            ++l[x]; ++r[y];
            use1[x][i]=1;
            use2[y][i]=1;
            use3[blo(x)][blo(y)][i]=1;
            dfs(step+1,tot+i*score[x][y],find());
            val[x][y]=0;
            --l[x]; --r[y];
            use1[x][i]=0;
            use2[y][i]=0;
            use3[blo(x)][blo(y)][i]=0; //回溯
        }
    }
    int main(){
        int tot=0,cnt=0;
        for(int i=1;i<=9;++i)
            for(int j=1;j<=9;++j){
                scanf("%d",&val[i][j]);
                if(!val[i][j]) continue;
                ++cnt; ++l[i]; ++r[j];
                use1[i][val[i][j]]=1; 
                use2[j][val[i][j]]=1;
                use3[blo(i)][blo(j)][val[i][j]]=1;
            }
        for(int i=5;i>=1;--i){
            int x1=i,x2=10-i,x3=i,x4=10-i;
            int y1=i,y2=i,y3=10-i,y4=10-i;
            for(int j=10-i;j>=i;--j){
                score[x1][y1]=i+5;
                score[x2][y2]=i+5;
                score[x3][y3]=i+5;
                score[x4][y4]=i+5;
                if(val[x1][y1]&&!vis[x1][y1]) tot+=val[x1][y1]*score[x1][y1],vis[x1][y1]=1;
                if(val[x2][y2]&&!vis[x2][y2]) tot+=val[x2][y2]*score[x2][y2],vis[x2][y2]=1;
                if(val[x3][y3]&&!vis[x3][y3]) tot+=val[x3][y3]*score[x3][y3],vis[x3][y3]=1;
                if(val[x4][y4]&&!vis[x4][y4]) tot+=val[x4][y4]*score[x4][y4],vis[x4][y4]=1;
                ++x1; ++y2; --y3; --x4;
            } //按照题意给出分数
        }
        dfs(cnt,tot,find());
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    PowerShell里的数组
    题解 cf gym 103261 D FFT Algorithm
    欧拉筛求积性函数的一般形式
    题解 LOJ 6053
    题解 SP34112 UDIVSUM
    题解 luogu P5162 WD与积木
    Java 关闭流同步输入输出
    题解 luogu P6620 [省选联考 2020 A 卷] 组合数问题
    hdu 6588 题解
    题解 cf gym 102979 E Expected Distance
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9588329.html
Copyright © 2011-2022 走看看