靶型数独

https://loj.ac/problem/2591

题目描述

  给出数独的一部分,并且每个位置的有一定分数,数独的总分数等于所有位置上的数值乘以其分数,求最大分数

思路

  首先直接爆搜肯定会T掉,我们就需要贪心的从一种较优解开始搜索。我采用的是一种较优的方法,先统计一遍每行已知的个数,然后在将行排序一遍,从已知数字最多的那一行逐列搜索,全部搜索完后统计答案即可。注意维护数独的各个信息就可以了。

代码

#include <bits/stdc++.h>
using namespace std;
int mp[10][10];
bool l[10][10],h[10][10],jg[10][10];
int ans;
int v[15][15]={{},{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}};
bool f;
struct Node
{
    int l,sum;
}ll[20];
int cmp(Node a,Node b)
{
    return a.sum<b.sum;
}
int change(int a,int b)
{
    return (b-1)/3+(a-1)/3*3+1;
}
void dfs(int x,int y,int ha)
{
    if(ha==10)
    {
        f=1;
        int sum=0;
        for(int i=1;i<=9;i++)
            for(int j=1;j<=9;j++)
                sum+=mp[i][j]*v[i][j];
        ans=max(ans,sum);
        return ;
    }
    if(y==10)
    {
        dfs(ll[ha+1].l,1,ha+1);
        return ;
    }
    if(!mp[x][y])
    {
        for(int num=1;num<=9;num++)
            if(!h[x][num]&&!l[y][num]&&!jg[change(x,y)][num])
            {
                mp[x][y]=num;h[x][num]=1;l[y][num]=1;jg[change(x,y)][num]=1;
                dfs(x,y+1,ha);
                mp[x][y]=0;h[x][num]=0;l[y][num]=0;jg[change(x,y)][num]=0;
            }
    }
    else dfs(x,y+1,ha);
}
int main() 
{
    for(int i=1;i<=9;i++)
    {
        int s=0;
        for(int j=1;j<=9;j++)
        {
            int a;
            scanf("%d",&a);
            if(!a)s++;
            mp[i][j]=a;h[i][a]=1;l[j][a]=1;
            jg[change(i,j)][a]=1;
        }
        ll[i].l=i;ll[i].sum=s;
    }
    sort(ll+1,ll+10,cmp);
    dfs(ll[1].l,1,1);
    if(f)printf("%d",ans);
    else printf("-1");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fangbozhen/p/11613847.html