这题数据这么小显然是搜索,但朴素的没法过,所以要想办法剪枝。
不走死胡同!所谓死胡同,就是走进去以后就再也无法走出来的点。
一种简单的想法是:"任意时刻,必须保证和当前所在位置不相邻的未经点至少有两个相邻的未经点"。基于这种想法,可以采取这样的优化:
该优化的力度很大,可以在0.2秒内解决N=6,但N=7仍然需要2秒左右的时间。
不要形成孤立的区域!如果行走过程中把路一分为二,那么肯定有一部分再也走不到了,需要剪枝。
形成孤立的区域的情况很多,如果使用Floodfill找连通块,代价会很大,反而会更慢。我只考虑了一种最容易出现特殊情况,即:
这样就会形成孤立的区域,只要将出现这种情况的状态都剪掉即可。
加上优化2,N=7也能在0.3s解决了。
代码:{ ID: ymwbegi1 PROG: betsy LANG: PASCAL } const dx:array[1..4] of longint=(0,1,0,-1); dy:array[1..4] of longint=(1,0,-1,0); var ans,n,i:longint; v:array[0..8,0..8] of boolean; function find(x,y:longint):longint; var i,p,q:longint; begin find:=0; for i:=1 to 4 do begin p:=x+dx[i]; q:=y+dy[i]; if (p<1)or(p>n)or(q<1)or(q>n) then continue; if v[p,q] then inc(find); end; end; procedure dfs(x,y,s:longint); var i,u,p,q:longint; begin inc(s); if (x=n)and(y=1) then begin if s=n*n then inc(ans); exit; end; u:=0; if (v[x+1,y])and(v[x-1,y])and(v[x,y+1]=false)and(v[x,y-1]=false) then exit; if (v[x,y+1])and(v[x,y-1])and(v[x+1,y]=false)and(v[x-1,y]=false) then exit; for i:=1 to 4 do begin p:=x+dx[i]; q:=y+dy[i]; if (p<1)or(p>n)or(q<1)or(q>n) then continue; if v[p,q]=false then continue; if (find(p,q)=1)and((p<>n)or(q<>1)) then begin if u>0 then exit; u:=i; end; end; if u>0 then begin p:=x+dx[u]; q:=y+dy[u]; v[p,q]:=false; dfs(p,q,s); v[p,q]:=true; end else for i:=1 to 4 do begin p:=x+dx[i]; q:=y+dy[i]; if (p<1)or(p>n)or(q<1)or(q>n) then continue; if v[p,q]=false then continue; v[p,q]:=false; dfs(p,q,s); v[p,q]:=true; end; end; begin assign(input,'betsy.in'); assign(output,'betsy.out'); reset(input); rewrite(output); readln(n); fillchar(v,sizeof(v),true); for i:=1 to n do begin v[0,i]:=false; v[n+1,i]:=false; v[i,0]:=false; v[i,n+1]:=false; end; v[1,1]:=false; dfs(1,1,0); writeln(ans); close(input); close(output); end.