Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
不需要DFS,只需BFS。有一个贪心策略,见内不需要DFS,只需每次贪心找出一个配对个数最少的方块(个数为0的不计)消去即可,用这个代替DFS。 这个方法至少我当前没有找到反例,以下是我的理解: 表达能力不强,的和心里想的有很大出入= =| 若当前找到的最少配对个数为k(为0的不计): 1° 若k>=2,当前无论如何操作都不会造成死局。 2° 若k=1,如果当前操作造成死局,换一种说法: 死局大体上无非就是两种情况: 所有的方块配对个数均为0。 经过某次操作后,以前配对个数不为0的某个方块变成了0,那么这次操作造成死局。 再换言之,当前k=1的点如果跟i消去,结果造成另一也只能和i配对的方块j失去了配对,这就是有可能造成死局的操作。而如果这种局面存在,无论进行其他任何操作都不能避免,因为i,j都要抢k。 可能会有人问:如果其他的一系列操作不会造成这种局面出现呢?我认为不存在这样的操作。因为按照上面的方法,每次选择的都是不会把好局变成死局的“优操作”,因为找的是最小配对个数的消去。这样一步步走下去,策略就应该是可行的。 证明极不严谨,希望各位有反例可以提出。至少这题是ac了。 赠一组数据: 3 4 ACDA CABD BCCA yes const dx:array[1..4]of integer=(-1,1,0,0); dy:array[1..4]of integer=(0,0,-1,1); dz:array[1..4]of integer=(1,2,3,4); var a:array[-1..12,-1..12]of longint; b:array[1..4]of longint; c,d:array[1..4,0..100]of longint; q:array[0..1000]of record x,y,dat,dir:longint; end; v:array[0..11,0..11,1..4]of longint; link:array[0..10,0..10]of boolean; n,m,i,j,k,tot,min,mi,mj,mx,my,kx,ky,l,r:longint; bool:boolean; ch:char; procedure scanf; begin fillchar(b,sizeof(b),0); fillchar(a,sizeof(a),255); for i:=0 to n+1 do begin a[i,0]:=0; a[i,m+1]:=0; end; for i:=0 to m+1 do begin a[0,i]:=0; a[n+1,i]:=0; end; tot:=0; for i:=1 to n do begin for j:=1 to m do begin read(ch); if ch='*' then a[i,j]:=0 else a[i,j]:=ord(ch)-64; if a[i,j]<>0 then begin k:=a[i,j]; inc(b[k]); c[k,b[k]]:=i; d[k,b[k]]:=j; inc(tot); end; end; readln; end; end; function bfs(sx,sy,z:longint):longint; var i,j,nx,ny,ndat,ndir:longint; begin bfs:=0; fillchar(v,sizeof(v),127); fillchar(link,sizeof(link),0); l:=1; r:=4; for i:=1 to 4 do with q[i] do begin x:=sx; y:=sy; dat:=0; dir:=i; v[sx,sy,i]:=0; end; while l<=r do with q[l] do begin for i:=1 to 4 do begin nx:=x+dx[i]; ny:=y+dy[i]; ndir:=dz[i]; if ndir<>dir then ndat:=dat+1 else ndat:=dat; if ndat>2 then continue; if (a[nx,ny]=z)and((nx<>sx)or(ny<>sy)) then link[nx,ny]:=true; if (a[nx,ny]=0)and(ndat<v[nx,ny,ndir]) then begin inc(r); q[r].x:=nx; q[r].y:=ny; q[r].dat:=ndat; q[r].dir:=ndir; v[nx,ny,ndir]:=ndat; end; end; inc(l); end; for i:=1 to n do for j:=1 to m do if link[i,j] then begin inc(bfs); kx:=i; ky:=j; end; end; begin repeat readln(n,m); if n=0 then exit; scanf; bool:=true; while tot>0 do begin min:=maxint; for i:=1 to 4 do for j:=1 to b[i] do begin if a[c[i,j],d[i,j]]=0 then continue; k:=bfs(c[i,j],d[i,j],i); if (k<min)and(k<>0) then begin min:=k; mi:=c[i,j]; mj:=d[i,j]; mx:=kx; my:=ky; end; end; if min=maxint then begin bool:=false; break; end; a[mi,mj]:=0; a[mx,my]:=0; dec(tot,2); end; if bool then writeln('yes') else writeln('no'); until false; end. Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator