Luogu 1074(DFS)(NOIP 2009)

传送门
NOIP 2009 T4 靶形数独
题解:暴搜,注意优化:
1.先填能选的比较少的格子
2.好像可以用链表剪枝,留坑待填(一时半会儿估计都填不好,有兴趣的读者可自行yy,祝你们顺利╮(╯_╰)╭)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=10;
int cnt=0,mp[MAXN][MAXN],ans=-1;
bool h[MAXN][MAXN],l[MAXN][MAXN],f[MAXN][MAXN],vis[MAXN*MAXN];
int x[MAXN*MAXN],y[MAXN*MAXN];
int bel[MAXN][MAXN]={
{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 val[MAXN][MAXN]={
{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},
};
/*void print() {
    for (int i=1;i<=9;++i) {
        for (int j=1;j<=9;++j)
            printf("%d ",mp[i][j]);
        puts("");
    }
    puts("");
}*/
void dfs(int step) {
    if (step>cnt) {
        int sum=0;
        for (int i=1;i<=9;++i)
            for (int j=1;j<=9;++j)
                sum+=mp[i][j]*val[i][j];

        ans=max(ans,sum);
        return ;
    }
    int mn=0x3f3f3f3f,pos;
    for (int i=1;i<=cnt;++i) {
        if (!vis[i]) {
            int temp=0;
            for (int j=1;j<=9;++j)
                if (!h[x[i]][j]&&!l[y[i]][j]&&!f[bel[x[i]][y[i]]][j])
                    if (++temp==mn) break;
            if (temp<mn) pos=i,mn=temp;
        }
    }
    vis[pos]=true;
    for (int j=1;j<=9;++j) {
        if (!h[x[pos]][j]&&!l[y[pos]][j]&&!f[bel[x[pos]][y[pos]]][j]) {
            h[x[pos]][j]=l[y[pos]][j]=f[bel[x[pos]][y[pos]]][j]=true;
            mp[x[pos]][y[pos]]=j;//print();
            dfs(step+1);
            h[x[pos]][j]=l[y[pos]][j]=f[bel[x[pos]][y[pos]]][j]=false;
        }
    }
    vis[pos]=false;
}
int main() {
//  freopen("P1074.in","r",stdin);
    memset(h,false,sizeof(h));
    memset(l,false,sizeof(l));
    memset(f,false,sizeof(f));
    for (int i=1;i<=9;++i)
        for (int j=1;j<=9;++j) {
            scanf("%d",&mp[i][j]);
            if (mp[i][j]) h[i][mp[i][j]]=l[j][mp[i][j]]=f[bel[i][j]][mp[i][j]]=true;
            else x[++cnt]=i,y[cnt]=j,vis[cnt]=false;
        }
    dfs(1);
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值