B3983
UPD:修正笔误。
信息与未来真神吧?拿这种东西给小学生做?
我的做法可能偏复杂了。
观察到
对于单个字符 LRUD,我们可以提前把它们对应的这两个矩阵算出来。
方便起见,我们把全部
当两段操作序列
由此并不显然有,
我们发现这个东西很像矩阵乘法。具体来讲,若乘法为
做这个乘法的复杂度是 std::bitset 或者 unsigned long long 或者 __int128 之类的东西压位,可以做到
对于
对于
然后全拼起来就做完了,总复杂度
这题既不入门,也不面试,但是它在入门与面试题库里面。综合算法难度,思维难度和代码难度,我觉得这应该是 B 题库最难的一题。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int dx[4]={0,0,-1,1};
const int dy[4]={-1,1,0,0};
char s[15][15],S[1005];
int n,m,N;
inline int id(int x,int y){
return (x-1)*m+y;
}
inline int getx(int x){
return (x-1)/m+1;
}
inline int gety(int x){
return (x-1)%m+1;
}
struct command{
command(){
for(int i=1;i<=N;i++){
to[i].reset();
path[i].reset();
}
}
bitset<105>to[105],path[105];
void operator |=(command o){
for(int i=1;i<=N;i++){
to[i]|=o.to[i];
path[i]|=o.path[i];
}
}
}com[505];
int cnt=0,readpos=0;
bitset<105>tr[105];
command concatenate(const command &x,const command &y){
command z;
for(int i=1;i<=N;i++)z.path[i]=x.path[i];
for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)if(x.to[i][j]){
z.to[i]|=y.to[j],z.path[i]|=y.path[j];
}
return z;
}
command repeat(command &x,int k){
for(int i=1;i<=N;i++)tr[i].reset();
command ans;
for(int i=1;i<=N;i++)ans.to[i][i]=1,ans.path[i][i]=1;
if(k<1 || k>9){
ans|=x;
for(int i=1;i<=N;i++)for(int j=1;j<=N;j++){
// Floyd 求最短路的时候我们有 dis[j][k] <--- dis[j][i]+dis[i][k],这里也是一样的道理。
if(ans.to[j][i]){
ans.to[j]|=ans.to[i];
ans.path[j]|=ans.path[i];
}
}
}
else{
command tmp=x;
while(k){
// 快速幂
if(k&1)ans=concatenate(ans,tmp);
tmp=concatenate(tmp,tmp);
k>>=1;
}
}
return ans;
}
int Len;
void walk(command &x,int dir){
for(int i=1;i<=N;i++)tr[i].reset();
for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)if(x.to[i][j]){
int nx=getx(j)+dx[dir],ny=gety(j)+dy[dir];
if(nx>=1 && nx<=n && ny>=1 && ny<=m && s[nx][ny]=='.')tr[i][j+dx[dir]*m+dy[dir]]=1;
else tr[i][j]=1;
}
for(int i=1;i<=N;i++)x.to[i]=tr[i],x.path[i]|=tr[i];
}
void readCommand(command &x){
for(int i=1;i<=N;i++){
x.to[i][i]=x.path[i][i]=1;
}
while(readpos<Len && S[readpos]!=')'){
char c=S[readpos];
// LRUD 可以做到 N^2 而不是 N^3/w
if(c=='L')walk(x,0);
if(c=='R')walk(x,1);
if(c=='U')walk(x,2);
if(c=='D')walk(x,3);
if(c=='('){
++readpos;
command &f=com[++cnt];
readCommand(f);
++readpos;
char op=S[readpos];
x=concatenate(x,repeat(f,op-48));
}
++readpos;
}
}
int main(){
scanf("%d%d",&n,&m);
N=n*m;
for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
scanf("%s",S);
Len=strlen(S);
readCommand(com[++cnt]);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s[i][j]=='#')putchar('#');
else if(com[1].path[id(1,1)][id(i,j)])putchar('+');
else putchar('.');
}
putchar('\n');
}
return 0;
}