CQOI2013 新数独题解
新数独
下面是一个没有数字,只有大小关系(没错!那些尖角都是“大于”符号!)的数独:
除了大小关系外(注意相邻格子不能相同),还需要满足通常的数独规则:
l 每个格子都是1~9 的数字
l 每行都是1~9的排列
l 每列都是1~9的排列
l 每个3*3的子矩阵(上图中用粗线隔开,一共有3*3个这样的子矩阵)都是1~9的排列
为了美观,每个3*3子矩阵的所有12对相邻格子的大小关系都将给出。
【输入格式】
输入一共15行,包含一个新数独的实例。第奇数行包含左右方向的符号(<和>),第偶数行包含上下方向的符号(^和v)。
【输出格式】
输出包含9行,每行9个1~9的数字,以单个空格隔开。输入保证解惟一。
【输入输出样例】
> < < < > <
v ^ v v ^ v ^ ^ v
< < < > < <
v ^ v ^ v v ^ ^ v
< < < < > >
< > > > < >
v v ^ ^ v ^ ^ v v
< > > < > >
^ v v v ^ v v ^ v
> < < > > >
< > > > > <
v v v v ^ ^ ^ ^ ^
> < < < < <
^ ^ ^ ^ ^ v v v ^
> > < > < <
5 3 9 4 6 8 2 1 7
2 4 8 1 9 7 3 5 6
1 6 7 2 3 5 9 8 4
6 8 1 7 4 2 5 9 3
3 7 5 9 1 6 8 4 2
9 2 4 5 8 3 7 6 1
7 9 6 8 2 1 4 3 5
4 1 2 3 5 9 6 7 8
8 5 3 6 7 4 1 2 9
考试拿到这个题不敢写啊,没想到直接搜都能得到满分。。。(无力吐槽)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
using
namespace
std;
const
int
INF=0x3f3f3f3f;
const
int
MAXN=110;
struct
Node{
int
v;
int
Flag;
Node *Next;
};
Node *adj[MAXN*10];
Node edge[MAXN*MAXN];
Node *Cnt1=&edge[0];
void
addedge(
int
u,
int
v,
int
Flag){
Node *p=++Cnt1;
p->v=v; p->Flag=Flag;p->Next=adj[u];
adj[u]=p;
}
int
High[MAXN*10],Low[MAXN*10];
inline
int
Get_Pos(
int
x,
int
y){
return
(x-1)*9+y;
}
int
Ans[MAXN*MAXN],visc[MAXN],visr[MAXN],visk[MAXN];
inline
int
Get_c(
int
x,
int
y){
return
y;
}
inline
int
Get_r(
int
x,
int
y){
return
x;
}
inline
int
Get_k(
int
x,
int
y){
return
(x%3==0?x/3-1:x/3)*3+(y%3==0?y/3:y/3+1);
}
void
DFS(
int
x,
int
y){
if
(x>9){
for
(
int
i=1;i<=9;++i){
for
(
int
j=1;j<=8;++j)
printf
(
"%d "
,Ans[Get_Pos(i,j)]);
printf
(
"%d\n"
,Ans[Get_Pos(i,9)]);
}
exit
(0);
}
if
(y>9){
DFS(x+1,1);
return
;
}
int
Pos=Get_Pos(x,y);
int
MaxSize=9,MinSize=1;
for
(Node *p=adj[Get_Pos(x,y)];p;p=p->Next){
int
v=p->v,Flag=p->Flag;
if
(Ans[v]!=INF){
if
(Flag==1){
MinSize=max(MinSize,Ans[v]+1);
}
else
{
MaxSize=min(MaxSize,Ans[v]-1);
}
}
}
for
(
int
a=max(MinSize,Low[Pos]);a<=min(MaxSize,High[Pos]);++a){
int
c,r,k;
c=Get_c(x,y); r=Get_r(x,y); k=Get_k(x,y);
if
((!(1<<a&visc[c]))&&(!(1<<a&visr[r]))&&(!(1<<a&visk[k])))
{
visc[c]^=(1<<a);
visr[r]^=(1<<a);
visk[k]^=(1<<a);
Ans[Get_Pos(x,y)]=a;
DFS(x,y+1);
visc[c]^=(1<<a);
visr[r]^=(1<<a);
visk[k]^=(1<<a);
Ans[Get_Pos(x,y)]=INF;
}
}
}
int
main()
{
//freopen("sudoku4.in","r",stdin);
for
(
int
i=0;i<MAXN*10;++i){
High[i]=9;
Low[i]=1;
}
memset
(Ans,0x3f,
sizeof
(Ans));
for
(
int
i=0;i<3;++i){
//分块
char
ch;
for
(
int
j=0;j<3;++j)
for
(
int
k=1;k<=2;++k){
do
{ch=
getchar
();}
while
(ch!=
'>'
&&ch!=
'<'
);
if
(ch==
'>'
){
Low[i*27+j*3+k]++;
High[i*27+j*3+k+1]--;
addedge(i*27+j*3+k,i*27+j*3+k+1,1);
addedge(i*27+j*3+k+1,i*27+j*3+k,0);
}
if
(ch==
'<'
){
High[i*27+j*3+k]--;
Low[i*27+j*3+k+1]++;
addedge(i*27+j*3+k,i*27+j*3+k+1,0);
addedge(i*27+j*3+k+1,i*27+j*3+k,1);
}
}
for
(
int
j=1;j<=9;++j){
do
{ch=
getchar
();}
while
(ch!=
'v'
&&ch!=
'^'
);
if
(ch==
'v'
){
Low[i*27+j]++;
High[i*27+j+9]--;
addedge(i*27+j,i*27+j+9,1);
addedge(i*27+j+9,i*27+j,0);
}
if
(ch==
'^'
){
High[i*27+j]--;
Low[i*27+j+9]++;
addedge(i*27+j,i*27+j+9,0);
addedge(i*27+j+9,i*27+j,1);
}
}
for
(
int
j=0;j<3;++j)
for
(
int
k=1;k<=2;++k){
do
{ch=
getchar
();}
while
(ch!=
'<'
&&ch!=
'>'
);
if
(ch==
'>'
){
Low[i*27+9+j*3+k]++;
High[i*27+9+j*3+k+1]--;
addedge(i*27+9+j*3+k,i*27+9+j*3+k+1,1);
addedge(i*27+9+j*3+k+1,i*27+9+j*3+k,0);
}
if
(ch==
'<'
){
High[i*27+9+j*3+k]--;
Low[i*27+9+j*3+k+1]++;
addedge(i*27+9+j*3+k,i*27+9+j*3+k+1,0);
addedge(i*27+9+j*3+k+1,i*27+9+j*3+k,1);
}
}
for
(
int
j=1;j<=9;++j){
do
{ch=
getchar
();}
while
(ch!=
'v'
&&ch!=
'^'
);
if
(ch==
'v'
){
Low[i*27+9+j]++;
High[i*27+18+j]--;
addedge(i*27+9+j,i*27+18+j,1);
addedge(i*27+18+j,i*27+9+j,0);
}
if
(ch==
'^'
){
High[i*27+9+j]--;
Low[i*27+18+j]++;
addedge(i*27+9+j,i*27+18+j,0);
addedge(i*27+18+j,i*27+9+j,1);
}
}
for
(
int
j=0;j<3;++j)
for
(
int
k=1;k<=2;++k){
do
{ch=
getchar
();}
while
(ch!=
'<'
&&ch!=
'>'
);
if
(ch==
'>'
){
Low[i*27+18+k+j*3]++;
High[i*27+18+k+1+j*3]--;
addedge(i*27+18+k+j*3,i*27+18+k+1+j*3,1);
addedge(i*27+18+k+j*3+1,i*27+18+k+j*3,0);
}
if
(ch==
'<'
){
High[i*27+18+k+j*3]--;
Low[i*27+18+k+1+j*3]++;
addedge(i*27+18+k+j*3,i*27+18+k+1+j*3,0);
addedge(i*27+18+k+j*3+1,i*27+18+k+j*3,1);
}
}
}
/*for(int i=1;i<=9;++i){
for(int j=1;j<=9;++j)
printf("%d ",High[Get_Pos(i,j)]);
printf("\n");
}
printf("\n");
for(int i=1;i<=9;++i){
for(int j=1;j<=9;++j)
printf("%d ",Low[Get_Pos(i,j)]);
printf("\n");
}
printf("\n");*/
DFS(1,1);
return
0;
}