1605: Target Sudoku
Time Limit: 4 Sec Memory Limit: 128 MBSubmit: 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;
}