noip 2009 靶型数独

靶型数独

一看就是搜索,DFS,

顺着搜卡时过了80分,

倒着搜卡时竟然全过了,

只能说数据比较合适倒着搜,貌似总是倒着搜要好一点——不知道为什么额。


有说用dancing links 的,但是不会,现在就去学


虽然是用不能AC的程序AC了,但还是贴出来。


除了3个布尔数组,实在也想不到什么能都剪枝的了。

const
v:array[1..9,1..9]of longint=
(
(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));
pa:array[1..9,1..9]of longint=
(
(1,1,1,2,2,2,3,3,3),
(1,1,1,2,2,2,3,3,3),
(1,1,1,2,2,2,3,3,3),
(4,4,4,5,5,5,6,6,6),
(4,4,4,5,5,5,6,6,6),
(4,4,4,5,5,5,6,6,6),
(7,7,7,8,8,8,9,9,9),
(7,7,7,8,8,8,9,9,9),
(7,7,7,8,8,8,9,9,9)
);
var
fa,fy,fx:array[1..9,1..9]of boolean;
i,j,lc,ans,yuan,ks:longint;
m:array[1..9,1..9]of longint;
lx,ly:array[1..81]of longint;

procedure dfs(t:longint);
var
	i,j,x,y,tem:longint;
begin
        inc(ks);
        if ks=10000000 then begin
                writeln(ans);
                halt;
        end;
        //write(t);
	if t=0 then begin
		tem:=yuan;
		for i:=1 to lc  do  tem:=v[lx[i],ly[i]]*m[lx[i],ly[i]]+tem;
		if tem>ans then ans:=tem;
		exit;
	end;
	x:=lx[t];
	y:=ly[t];
	for i:=1 to 9 do
		if fa[i,pa[x,y]] and fx[i,x] and fy[i,y]then begin
			fa[i,pa[x,y]]:=false;
			fx[i,x]:=false;
			fy[i,y]:=false;
			m[x,y]:=i;
			dfs(t-1);
			fa[i,pa[x,y]]:=true;
			fx[i,x]:=true;
			fy[i,y]:=true;
		end;
end;
begin
fillchar(fx,sizeof(fx),true);
fillchar(fy,sizeof(fy),true);
fillchar(fa,sizeof(fa),true);
ks:=0;
lc:=0;
ans:=-1;
yuan:=0;
for i:=1 to 9 do
	for j:=1 to 9 do begin
		read(m[i,j]);
		if m[i,j]=0 then begin
			inc(lc);
			lx[lc]:=i;
			ly[lc]:=j;
		end else begin
			fa[m[i,j],pa[i,j]]:=false;
			fx[m[i,j],i]:=false;
			fy[m[i,j],j]:=false;
			yuan:=yuan+m[i,j]*v[i,j];
		end;
	end;
	dfs(lc);
	writeln(ans);
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值