您的位置:首页 > 其它

【NOI2017模拟4.5】机器人游戏

2017-04-10 10:46 363 查看

题目

Description

小A和小B在一个R行S列的棋盘上玩游戏,棋盘上的每一个棋格都有一个方向标记(上、下、左或右)。游戏按如下方式进行:

小A先将K个棋格涂上黑色(初始为白色),并且他不能涂黑最后一列的棋格;随后,小B在第一列的任意一个棋格上放一个小机器人;此时,小机器人将会不停地沿着他所在的棋格所指示的方向走到一个相邻的棋格,直到他到达最后一列的棋格,游戏结束。

游戏胜负规则如下:

●如果小机器人最终到达最后一列,且在游戏过程中经过了恰好一个黑色棋格(包括小机器人开始的棋格),那么小A获得胜利;如果小机器人经过了零个或大于一个黑色格子,那么小B获得胜利。

●如果机器人永远无法停下来,那么小A胜利。

题目保证每个棋格上的方向标记不会让小机器人走到棋盘外。

棋盘示意图如下:

现在小A想知道,他是否能找到一种涂黑格子的方案,使得不论小B如何放置游戏开始时的小机器人,他都能取得游戏的胜利。

Input

第一行包含三个正整数R,S,K(1<=R*S<=1,000,000,1<=K<=50)。

接下来R行,每行S个字符’L’(左),’R’(右),’U’(上),’D’(下),表示每个棋格的方向标志。

Output

如果小A没有必胜策略,输出-1。

否则,输出K行,每行两个正整数A,B(1<=A<=R,1<=B<=S)表示小A要涂黑的棋格。输出不能有两个相同的棋格。

如果有多种不同的方案,输出任意一种即可。

Sample Input

输入1:

4 3 1

DRD

DUD

DUD

RUL

输入2:

3 3 2

RRR

RRR

RRR

输入3:

4 4 2

RRDL

RRDL

DLRD

RRRL

题解

考虑建一颗树来解决这个问题

我们先把所有的箭头都反向,把最后一列整体看成一个节点,然后按照箭头连边

容易发现,如果一颗子树里的每一个节点都不是第一列的,那么这颗子树中所有节点都可以涂黑可以不涂黑,现在关键是如何处理其他的节点

考虑用一个dp解决这个问题,设f[i,j]表示以i为根的子树里面j个涂黑是否可以合法,转移显然

得到答案之后我们可以从根开始再做一遍dfs,随便找一下选哪一些点就可以了

但是我们发现这样会超时,于是打一个水优化,就是树里面可能会有一些连续的且不经过第一列的链,我们可以把这个链缩成一个点,这样实际复杂度就变得十分的优秀了

贴代码

var
go:array[1..4,1..2]of longint=((-1,0),(0,1),(1,0),(0,-1));
h,a,fa,fi:array[0..1000005]of longint;
son:array[0..1000005,0..4]of longint;
f,g:array[0..1000005,0..51]of boolean;
cc,pc:array[0..55,0..55]of longint;
bz,bc:array[0..1000005]of boolean;
dui:array[1..4]of longint=(3,4,1,2);
i,j,k,l,r,s,kk,x,y,z,n,ss,cq:longint;
ch:char;
bt:boolean;
function zhuan(x,y:longint):longint;
begin
bt:=false;
if y=1 then
begin
if x<=s then bt:=true;
exit(x-s);
end else
if y=3 then
begin
if x+s>r*s then bt:=true;
exit(x+s);
end else
if y=2 then
begin
if x mod s=0 then bt:=true;
exit(x+1);
end else
begin
if x mod s=1 then bt:=true;
exit(x-1);
end;
end;
procedure bfs;
var
yy:longint;
begin
i:=x;
j:=0;
while i>j do
begin
inc(j);
x:=h[j];
for k:=1 to 4 do
begin
y:=zhuan(x,k);
if (bt=true) or (bz[y]=true) or (a[y]<>dui[k]) then continue;
if y mod s=0 then continue;
fa[y]:=x;
if y mod s=1 then
begin
yy:=y;
while (bc[yy]=false) and (yy<>0) do
begin
if yy mod s=0 then
begin
yy:=yy;
end;
bc[yy]:=true;
yy:=fa[yy];
inc(ss);
end;
end;
inc(son[x,0]);
son[x,son[x,0]]:=y;
inc(i);
h[i]:=y;
bz[y]:=true;
end;
end;
end;
procedure dfs(x:longint);
var
i,j,k,ci:longint;
begin
f[x,0]:=true;
ci:=0;
while (son[x,0]=1) and (son[son[x,1],0]<>0) do
begin
if son[x,1] mod s=1 then break;
son[x]:=son[son[x,1]];
end;
for i:=1 to son[x,0] do
if bc[son[x,i]]=true then
begin
dfs(son[x,i]);
if (x-1) mod s=0 then continue;
for j:=1 to kk do g[x,j]:=false;
for j:=kk downto 1 do
begin
//if f[son[x,i],j]=false then f[x,j]:=false;
if f[x,j]=false then
for k:=0 to j-1 do
if (f[son[x,i],j-k]=true) and (f[x,k]=true) then g[x,j]:=true;
end;
for j:=0 to kk do f[x,j]:=g[x,j];
end;
f[x,0]:=false;
f[x,1]:=true;
if x=11 then
begin
x:=x;
end;
end;
procedure back(x,y:longint);
var
i,j,ls:longint;
pc,cc:array[0..55,0..55]of longint;
begin
fillchar(cc,sizeof(cc),0);
fillchar(pc,sizeof(pc),0);
for i:=1 to y do f[x,i]:=false;
f[x,0]:=true;
for i:=1 to son[x,0] do
if bc[son[x,i]]=true then
begin
for j:=1 to y do g[x,j]:=false;
for j:=y downto 1 do
begin
//if f[son[x,i],j]=false then f[x,j]:=false;
for k:=0 to j-1 do
if (f[son[x,i],j-k]=true) and (f[x,k]=true) then
begin
g[x,j]:=true;
cc[j]:=cc[k];
pc[j]:=pc[k];
inc(cc[j,0]); cc[j,cc[j,0]]:=son[x,i];
pc[j,cc[j,0]]:=j-k;
end;
end;
for j:=0 to kk do f[x,j]:=g[x,j];
end;
for i:=1 to cc[y,0] do
begin
if pc[y,i]=1 then writeln(cc[y,i] div s+1,' ',cc[y,i] mod s) else
back(cc[y,i],pc[y,i]);
end;
end;
begin
assign(input,'robots.in'); reset(input);
assign(output,'robots.out'); rewrite(output);
readln(r,s,kk);
for i:=1 to r do
begin
for j:=1 to s do
begin
read(ch);
if ch='U' then x:=1 else
if ch='R' then x:=2 else
if ch='D' then x:=3 else
if ch='L' then x:=4;
a[(i-1)*s+j]:=x;
end;
readln;
end;
x:=0;
for i:=1 to r do
if a[(i-1)*s+s-1]=2 then
begin
inc(x);
h[x]:=(i-1)*s+s-1;
bz[(i-1)*s+s-1]:=true;
fi[x]:=h[x];
end;
n:=x;
bfs;
for i:=1 to n do
if bc[fi[i]]=true then
dfs(fi[i]);
f[r*s,0]:=true;
for i:=1 to n do
if bc[fi[i]]=true then
begin
for j:=1 to kk do g[r*s,j]:=false;
for j:=kk downto 1 do
begin
//if f[fi[i],j]=false then f[r*s,j]:=false;
for k:=0 to j-1 do
if (f[fi[i],j-k]=true) and (f[r*s,k]=true) then
begin
g[r*s,j]:=true;
cc[j]:=cc[k];
pc[j]:=pc[k];
inc(cc[j,0]); cc[j,cc[j,0]]:=i;
pc[j,cc[j,0]]:=j-k;
end;
end;
for j:=0 to kk do f[r*s,j]:=g[r*s,j];
end;
bt:=false;
ss:=r*(s-1)-ss;
cq:=kk-ss; if cq<0 then cq:=0;
for i:=kk downto cq do
if (f[r*s,i]=true) then
begin
bt:=true;
k:=i;
for j:=1 to r*s do if (j mod s>1) and (bc[j]=false) then
begin
if k=kk then break;
writeln(j div s+1,' ',j mod s);
inc(k);
end;
break;
end;
if bt=false then writeln(-1) else
begin
kk:=i;
j:=1;
for i:=1 to n do
if cc[kk,j]=i then
begin
if pc[kk,j]=1 then
begin
writeln(fi[i] div s+1,' ',fi[i] mod s);
inc(j);
continue;
end;
back(fi[i],pc[kk,j]);
inc(j);
if j>cc[kk,0] then break;
end;
end;
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: