我们要干的事情其实是对于输入矩阵中的每个位置,求出从它开始至少走几步形成的序列能跟所有位置走同样步数形成的序列不同。注意到每个位置至少走\(200^2\)步就能达到目标了,所以这时就有了一个\(O(n^4)\)的暴搜(把trie树搜出来),如果写得好是可以卡过去的!
但是还有更优的做法。注意到题目中说,输入的矩阵中最多只有100个X。所以可以对矩阵中的每个位置求出一个长度最多为100的序列,表示从这个位置开始走,形成的序列中的哪些位置是X。这一步可以做到\(O(n^3logn)\)(X的数量与n同阶,所以也用n表示了)。这时就可以用这些长为100的序列跑上面的暴搜,每次将一些位置分开的时候可以用map存。这一步的复杂度也是\(O(n^3logn)\)。
总复杂度\(O(n^3logn)\)。
点击查看代码
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <int,int>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back
void fileio()
{
#ifdef LGS
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
void termin()
{
#ifdef LGS
std::cout<<"\n\nPROGRAM TERMINATED";
#endif
exit(0);
}
using namespace std;
int n,m,mxstp=42000,mx=-1;
vector <pii> mxs,stps;
double sum=0;
string s[110];
vector <int> times[110][110];
map <pii,int> mp;
void dfs(vector <pii> v,int ti,int pos)
{
if(v.size()==1)
{
sum+=ti;
if(mx<ti){mx=ti;mxs={v[0]};}
else if(mx==ti) mxs.pb(v[0]);
return;
}
map <int,vector <pii> > mpp;
rep(i,v.size()) mpp[times[v[i].fi][v[i].se][pos]].pb(v[i]);
if(mpp.size()==1) dfs(v,ti,pos+1);
else
{
int lstti=-1;
for(auto it=mpp.begin();it!=mpp.end();++it)
{
if(it==(--mpp.end())) dfs(it->se,lstti,pos+1);
else
{
lstti=it->fi;
dfs(it->se,lstti,pos+1);
}
}
}
}
int main()
{
fileio();
cin>>m>>n;
rep(i,n) cin>>s[i];
repn(i,114514)
{
if(i%2==1)
{
rep(j,i) if(stps.size()<mxstp) stps.pb(mpr(-1,0));
rep(j,i) if(stps.size()<mxstp) stps.pb(mpr(0,1));
}
else
{
rep(j,i) if(stps.size()<mxstp) stps.pb(mpr(1,0));
rep(j,i) if(stps.size()<mxstp) stps.pb(mpr(0,-1));
}
if(stps.size()>=mxstp) break;
}
int curx=0,cury=0;
rep(i,stps.size())
{
mp[mpr(curx,cury)]=i;
curx+=stps[i].fi;cury+=stps[i].se;
}
rep(i,n) rep(j,m) if(s[i][j]=='X')
{
rep(ii,n) rep(jj,m)
times[ii][jj].pb(mp[mpr(i-ii,j-jj)]);
}
rep(i,n) rep(j,m) sort(times[i][j].begin(),times[i][j].end()),times[i][j].pb(114514);
vector <pii> vv;rep(i,n) rep(j,m) vv.pb(mpr(i,j));
dfs(vv,0,0);
printf("%.3lf\n%d\n",sum/n/m,mx);
rep(i,mxs.size()) mxs[i]=mpr(mxs[i].se+1,n-mxs[i].fi);
sort(mxs.begin(),mxs.end(),[](pii xx,pii yy){if(xx.se!=yy.se) return xx.se<yy.se;return xx.fi<yy.fi;});
rep(i,mxs.size()) printf("(%d,%d) ",mxs[i].fi,mxs[i].se);
puts("");
termin();
}