您的位置:首页 > 其它

codeforces 596E Wilbur and Strings(DFS)

2015-11-24 21:53 281 查看
题目链接

E. Wilbur and Strings

time limit per test
3 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

Wilbur the pig now wants to play with strings. He has found an
n by m table consisting only of the digits from
0 to 9 where the rows are numbered
1 to n and the columns are numbered
1 to m. Wilbur starts at some square and makes certain moves. If he is at square (x,
y) and the digit d (0 ≤ d ≤ 9) is written at position (x,
y), then he must move to the square (x + ad,
y + bd), if that square lies within the table, and he stays in the square (x,
y) otherwise. Before Wilbur makes a move, he can choose whether or not to write the digit written in this square on the white board. All digits written on the whiteboard form some string. Every time a new digit is written,
it goes to the end of the current string.

Wilbur has q strings that he is worried about. For each string
si, Wilbur wants to know whether there exists a starting position (x,
y) so that by making finitely many moves, Wilbur can end up with the string
si written on the white board.

Input
The first line of the input consists of three integers
n, m, and
q (1 ≤ n, m, q ≤ 200) — the dimensions of the table and the number of strings to process, respectively.

Each of the next n lines contains
m digits from 0 and
9 giving the table itself.

Then follow 10 lines. The
i-th of them contains the values ai - 1 and
bi - 1 ( - 200 ≤ ai, bi ≤ 200), i.e. the vector that
Wilbur uses to make a move from the square with a digit i - 1 in it.

There are q lines that follow. The
i-th of them will contain a string si consisting only of digits from
0 to 9. It is guaranteed that the total length of these
q strings won't exceed
1 000 000.

Output
For each of the q strings, print "YES" if Wilbur can choose
x and y in order to finish with this string after some finite number of moves. If it's impossible, than print "NO" for the corresponding string.

Sample test(s)

Input
1 1 2
0
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
0000000000000
2413423432432


Output
YES
NO


Input
4 2 5
01
23
45
67
0 1
0 -1
0 1
0 -1
0 1
0 -1
0 1
0 -1
0 1
0 -1
0000000000
010101011101
32232232322
44343222342444324
6767


Output
YES
YES
YES NOYES


Note
In the first sample, there is a 1 by
1 table consisting of the only digit 0. The only move that can be made is staying on the square. The first string can be written on the white board by writing
0 repeatedly. The second string cannot be written as there is no
2 on the table.

题意:n*m的矩阵,每个格子内有一个(0-9)的数字。若当前在格子(i,j)那么下一步必须前往格子(i+a[i],j+b[j])(当且仅当该格子在矩阵内,否则任然在原地)。到了一个格子可以选择盖格子上的数字并将它加入已选数字的末尾,也可以不选。有q次询问,每次询问一个字符串,求解任选起点,在有限的步数内能否获得该字符串。

题解:根据题意建图。有一个特点,每一个格子出度最大为1。那么以任意一个点为起点一直走,那么路径一定唯一,末尾要么是个点,要么是个环。我们把环缩点,再反向建图,每次询问的一个字符串的时候,从入度为0的点开始,DFS遍历图,能匹配则匹配,贪心求解即可。由于图是个DAG,每个点的入度最大为1,那么每次询问,每个点最多只访问一次。复杂度O(q*n*m)

代码如下:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<list>
typedef __int64 LL;
typedef unsigned __int64 LLU;
const int nn=210;
const int inf=0x3fffffff;
const LL inf64=(LL)inf*inf;
using namespace std;
int n,m,q;
char stu[nn][nn];
int sz[nn*nn];
int tu[nn][nn];
int a[nn],b[nn];
char s[nn*10000];
struct node
{
int en,next;
}E[nn*nn];
int p[nn*nn],num;
int rd[nn*nn];
void init()
{
memset(rd,0,sizeof(rd));
memset(p,-1,sizeof(p));
num=0;
}
void add(int st,int en)
{
rd[en]++;
E[num].en=en;
E[num].next=p[st];
p[st]=num++;
}
bool check(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
}
int ID(int x,int y)
{
return (x-1)*m+y;
}
int dfn[nn*nn],low[nn*nn];
int cnt;
bool insta[nn*nn];
stack<int>sta;
bool use[nn*nn][15];
bool vis[nn*nn];
void dfs(int id)
{
sta.push(id);
insta[id]=true;
dfn[id]=low[id]=++cnt;
int i,w;
for(i=p[id];i+1;i=E[i].next)
{
w=E[i].en;
if(dfn[w]==-1)
{
dfs(w);
low[id]=min(low[id],low[w]);
}
else if(insta[w])
{
low[id]=min(low[id],dfn[w]);
}
}
if(dfn[id]==low[id])
{
while(1)
{
int ix=sta.top();
if(ix!=id)
{
vis[ix]=false;
rd[id]=0;
}
sta.pop();
insta[ix]=false;
use[id][sz[ix]]=true;
if(ix==id)
break;
}
}
}
void tarjan()
{
memset(dfn,-1,sizeof(dfn));
memset(insta,false,sizeof(insta));
memset(use,false,sizeof(use));
memset(vis,true,sizeof(vis));
cnt=0;
int i,j,w;
for(i=1;i<=n*m;i++)
{
if(dfn[i]==-1)
{
dfs(i);
}
}
}
bool solve(int id,int ix)
{
if(ix==-1)
return true;
int i,w;
bool re=false;
for(i=p[id];i+1;i=E[i].next)
{
w=E[i].en;
if(!vis[w])
continue;
if(use[w][s[ix]-'0'])
{
re=re||solve(w,ix-1);
}
else
{
re=re||solve(w,ix);
}
}
return re;
}
int main()
{
int i,j;
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%s",stu[i]);
for(j=0;j<m;j++)
{
tu[i][j+1]=stu[i][j]-'0';
sz[ID(i,j+1)]=tu[i][j+1];
}
}
for(i=0;i<=9;i++)
{
scanf("%d%d",&a[i],&b[i]);
}
init();
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(check(i+a[tu[i][j]],j+b[tu[i][j]]))
{
add(ID(i+a[tu[i][j]],j+b[tu[i][j]]),ID(i,j));
}
}
}

tarjan();
while(q--)
{
scanf("%s",s);
int ls=strlen(s);
for(i=1;i<=n*m;i++)
{
if(rd[i]==0)
{
int fuck=ls;
while(fuck>=1)
{
if(use[i][s[fuck-1]-'0'])
{
fuck--;
}
else
break;
}
if(fuck==0)
{
puts("YES");
break;
}
if(solve(i,fuck-1))
{
puts("YES");
break;
}
}
}
if(i>n*m)
{
puts("NO");
}
}
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: