csu 1605: Target Sudoku(Dancing Links)

1605: Target Sudoku

Time Limit: 4 Sec   Memory Limit: 128 MB
Submit: 59   Solved: 11
[ Submit][ Status][ Web Board]

Description

Xiao Cheng and Xiao Hua are fans of Sudoku. Recently, They planned to play a Sudoku game. However, ordinary Sudoku is too simple for them, so they asked Dr Z for help.
Dr Z took out his latest invention "Target Sudoku". In this Sudoku, every grid has its own weight, the number filled in the grid multiplying the weight of the grid is the score of the gird. The total score is equal to the sum of each score of the grid. The weight of each grid is shown as below. The grids share one color have the same weight.

Now, Xiao Cheng, who is eager to win, is asking for you to find out the most scores he can get for a given Target Sudoku.

Input

The first line there is a number T (0 < T <= 20), denoting the number of test cases.
Each test case has 9 lines, each line has 9 digits from 0 to 9, describing a Target Sudoku partly filled with numbers. The number 0 means the grid that have not been filled.

Output

For each case, output the most scores for the given Target Sudoku. If there is no solution, output -1 instead.

Sample Input

2
7 0 0 9 0 0 0 0 1
1 0 0 0 0 5 9 0 0
0 0 0 2 0 0 0 8 0
0 0 5 0 2 0 0 0 3
0 0 0 0 0 0 6 4 8
4 1 3 0 0 0 0 0 0
0 0 7 0 0 2 0 9 0
2 0 1 0 6 0 8 0 4
0 8 0 5 0 4 0 1 2
0 0 0 7 0 2 4 5 3
9 0 0 0 0 8 0 0 0
7 4 0 0 0 5 0 1 0
1 9 5 0 8 0 0 0 0
0 7 0 0 0 0 0 2 5
0 3 0 5 7 9 1 0 8
0 0 0 6 0 1 0 0 0
0 6 0 9 0 0 0 0 1
0 0 0 0 0 0 0 0 6

Sample Output

2829
2852

数独游戏  但是每个位置上有一些权值 最后的分数为每个位置上的数与权值乘积的和  求出最大的分数


Dancing Links进行搜索 求出一种可行解之后 按要求求出当前的分数  取最大值

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>

#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)

using namespace std;

const int N=9;
const int MAXN=N*N*N+10;
const int MAXM=N*N*4+10;
const int maxnode=MAXN*4+MAXM+10;
int ch[MAXN];
int mx;
int mul[9][9]={6,6,6,6,6,6,6,6,6,
               6,7,7,7,7,7,7,7,6,
               6,7,8,8,8,8,8,7,6,
               6,7,8,9,9,9,8,7,6,
               6,7,8,9,10,9,8,7,6,
               6,7,8,9,9,9,8,7,6,
               6,7,8,8,8,8,8,7,6,
               6,7,7,7,7,7,7,7,6,
               6,6,6,6,6,6,6,6,6,
               };

struct DLX
{
    int n,m,size;
    int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
    int H[MAXN], S[MAXM];
    int ansd, ans[MAXN];
    void init(int _n,int _m)
    {
        n = _n;
        m = _m;
        for(int i = 0;i <= m;i++)
        {
            S[i] = 0;
            U[i] = D[i] = i;
            L[i] = i-1;
            R[i] = i+1;
        }
        R[m] = 0; L[0] = m;
        size = m;
        for(int i = 1;i <= n;i++)
            H[i] = -1;
    }
    void Link(int r,int c)
    {
        ++S[Col[++size]=c];
        Row[size] = r;
        D[size] = D[c];
        U[D[c]] = size;
        U[size] = c;
        D[c] = size;
        if(H[r] < 0)H[r] = L[size] = R[size] = size;
        else
        {
            R[size] = R[H[r]];
            L[R[H[r]]] = size;
            L[size] = H[r];
            R[H[r]] = size;
        }
    }
    void remove(int c)
    {
        L[R[c]] = L[c]; R[L[c]] = R[c];
        for(int i = D[c];i != c;i = D[i])
            for(int j = R[i];j != i;j = R[j])
            {
                U[D[j]] = U[j];
                D[U[j]] = D[j];
                --S[Col[j]];
            }
    }
    void resume(int c)
    {
        for(int i = U[c];i != c;i = U[i])
            for(int j = L[i];j != i;j = L[j])
                ++S[Col[U[D[j]]=D[U[j]]=j]];
        L[R[c]] = R[L[c]] = c;
    }
    //d为递归深度
    bool Dance(int d)
    {
        if(R[0] == 0)
        {
//            cout<<"d "<<d<<endl;
            for(int i=0;i<d;i++) ch[(ans[i]-1)/9]=(ans[i]-1)%9+1;
            int sum=0;
            for(int i=0;i<N*N;i++)
            {
                int nn=i/N;
                int mm=i%N;
//                cout<<ch[i];
//                if(mm==8)
//                    puts("");
                sum+=ch[i]*mul[nn][mm];//根据每个位置的权  求出和
            }
            mx=max(mx,sum);
//            cout<<mx<<endl;
            return 1;
        }
        int flag=0;
        int c = R[0];
        for(int i = R[0];i != 0;i = R[i])
            if(S[i] < S[c])
                c = i;
        remove(c);
        for(int i = D[c];i != c;i = D[i])
        {
            ans[d] = Row[i];
            for(int j = R[i]; j != i;j = R[j])remove(Col[j]);
            if(Dance(d+1)) flag=1;//这里不能直接返回1  需要继续计算  求出所有情况中的最大值
            for(int j = L[i]; j != i;j = L[j])resume(Col[j]);
        }
        resume(c);
        return flag;
    }
}dlx;
void place(int &r,int &c1,int &c2,int &c3,int &c4,int i,int j,int k)
{
    r=(i*N+j)*N+k; c1=i*N+j+1; c2=N*N+i*N+k;
    c3=N*N*2+j*N+k; c4=N*N*3+((i/3)*3+(j/3))*N+k;
}


int main()
{
//    fread;
    int tc;
    scanf("%d",&tc);
    while(tc--)
    {
        mx=-1;
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                scanf("%d",&ch[i*N+j]);
        dlx.init(N*N*N,N*N*4);
        int r,c1,c2,c3,c4;
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                for(int k=1;k<=N;k++)
                    if(ch[i*N+j]==0||ch[i*N+j]==k)
        {
            place(r,c1,c2,c3,c4,i,j,k);
            dlx.Link(r,c1);
            dlx.Link(r,c2);
            dlx.Link(r,c3);
            dlx.Link(r,c4);
        }
        bool flag=dlx.Dance(0);
        if(!flag)
            puts("-1");
        else
            printf("%d\n",mx);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值