题目描述
小A和小B在一个R行S列的棋盘上玩游戏,棋盘上的每一个棋格都有一个方向标记(上、下、左或右)。游戏按如下方式进行:
小A先将K个棋格涂上黑色(初始为白色),并且他不能涂黑最后一列的棋格;随后,小B在第一列的任意一个棋格上放一个小机器人;此时,小机器人将会不停地沿着他所在的棋格所指示的方向走到一个相邻的棋格,直到他到达最后一列的棋格,游戏结束。
游戏胜负规则如下:
●如果小机器人最终到达最后一列,且在游戏过程中经过了恰好一个黑色棋格(包括小机器人开始的棋格),那么小A获得胜利;如果小机器人经过了零个或大于一个黑色格子,那么小B获得胜利。
●如果机器人永远无法停下来,那么小A胜利。
题目保证每个棋格上的方向标记不会让小机器人走到棋盘外。
现在小A想知道,他是否能找到一种涂黑格子的方案,使得不论小B如何放置游戏开始时的小机器人,他都能取得游戏的胜利。
DP
形成环的和无用点都随便选。
剩余形成树,类似树形依赖DP即可。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
#define id(i,j) ((i-1)*m+j)
using namespace std;
const int maxn=1000000+10;
bool f[maxn][55];
int g[maxn][55];
bool gg[maxn][55];
int h[maxn],go[maxn],next[maxn],fa[maxn],rec[maxn][2],ans[55][2];
int dfn[maxn],nfd[maxn],L[maxn],size[maxn],sta[80],c[maxn];
bool bz[maxn],pd[maxn];
int i,j,k,l,r,t,n,m,wdc,tot,top,euler,cnt,num,sum;
bool czy;
char ch;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
char get(){
char ch=getchar();
while (ch!='L'&&ch!='R'&&ch!='U'&&ch!='D') ch=getchar();
return ch;
}
void add(int x,int y){
go[++tot]=y;
next[tot]=h[x];
h[x]=tot;
}
int getfa(int x){
return fa[x]?fa[x]=getfa(fa[x]):x;
}
void link(int x,int y){
add(y,x);
int a=getfa(x),b=getfa(y);
if (a==b){
pd[a]=1;
return;
}
pd[b]|=pd[a];
fa[a]=b;
}
void dfs(int x){
if (rec[x][1]==1) bz[x]=1;
int t=h[x];
while (t){
dfs(go[t]);
bz[x]|=bz[go[t]];
t=next[t];
}
}
void dg(int x){
if (!bz[x]) return;
dfn[x]=++cnt;
nfd[cnt]=x;
size[x]=1;
if (rec[x][1]==1){
L[x]=++num;
return;
}
L[x]=10000000;
int t=h[x];
while (t){
if (bz[go[t]]){
dg(go[t]);
size[x]+=size[go[t]];
L[x]=min(L[x],L[go[t]]);
}
t=next[t];
}
}
void write(int x){
if (!x){
putchar('0');
return;
}
top=0;
while (x){
sta[++top]=x%10;
x/=10;
}
while (top) putchar('0'+sta[top--]);
}
int main(){
freopen("robots.in","r",stdin);freopen("robots.out","w",stdout);
czy=1;
n=read();m=read();k=read();
fo(i,1,n)
fo(j,1,m){
t=id(i,j);
rec[t][0]=i;rec[t][1]=j;
}
fo(i,1,n)
fo(j,1,m){
ch=get();
if (j==m) continue;
if (ch=='U') t=id(i-1,j);
else if (ch=='D') t=id(i+1,j);
else if (ch=='L') t=id(i,j-1);
else t=id(i,j+1);
link(id(i,j),t);
}
wdc=n*m+1;
fo(i,1,n*m)
if (!fa[i]&&!pd[i]) link(i,wdc);
dfs(wdc);
dg(wdc);
fo(i,1,n*m)
if (rec[i][1]!=m&&(pd[getfa(i)]||!bz[i])) c[++sum]=i;
f[1][0]=1;
fo(i,1,cnt)
fo(j,0,k)
if (f[i][j]){
t=nfd[i];
if (!f[i+1][j]&&L[nfd[i+1]]==L[t]){
f[i+1][j]=1;
g[i+1][j]=i;
gg[i+1][j]=0;
}
if (!f[i+size[t]][j+1]&&rec[t][1]<m&&rec[t][1]>0&&j<k){
f[i+size[t]][j+1]=1;
g[i+size[t]][j+1]=i;
gg[i+size[t]][j+1]=1;
}
}
fd(j,k,-1)
if (j<0||f[cnt+1][j]) break;
if (j<0||k-j>sum){
printf("-1\n");
return 0;
}
l=j;
i=cnt+1;
while (j){
r=g[i][j];
if (gg[i][j]){
t=nfd[g[i][j]];
ans[j][0]=rec[t][0];
ans[j][1]=rec[t][1];
j--;
}
i=r;
}
fo(i,l+1,k){
t=c[i-l];
ans[i][0]=rec[t][0];
ans[i][1]=rec[t][1];
}
fo(i,1,k){
write(ans[i][0]);putchar(' ');
write(ans[i][1]);putchar('\n');
}
}