@AkamemakA
2022-08-22T11:37:06.000000Z
字数 2147
阅读 194
Atcoder
题解
题目链接:点我
一个人初始在的位置。他有一个传送器。他会进行次操作,每次操作进行一下三种中的一种(当前他在的位置):
另外,在地图上有个点有障碍物。这个人不能传送到这些点上。
问这个人从初始点开始,经过次操作后能得到多少不同的路径。答案对取模。
第一行输入,第二行输入,接下来行,每行两个整数,表示障碍物的坐标。
2 2
1 1 1 2 1 3
1 2
2 2
5
有以下五条路径:
10 3
-1000000000 -1000000000 1000000000 1000000000 -1000000000 1000000000
-1000000000 -1000000000
1000000000 1000000000
-1000000000 1000000000
0
300 0
0 0 1 0 0 1
292172978
本蒟蒻第一次考场拿下第五题!!!(纪念一下)
首先想到的是最最最暴力的,时间复杂度,(铁定能过)
一般对于这种数路径,又有模数的问题,很容易就想到。
但这道题的地图是无限大的,所以不可能枚举点。然而我们发现,如果我们确定了三种操作的次数,那么这个人最终到达的点也可以被确定。因此,我们不妨枚举三个操作所用的次数,这样就可以知道当前这个人在那个点,如下:
//三层枚举
int gx=i*A+j*C+k*E;
int gy=i*B+j*D+k*F;
定义表示这个人走到表示的点处的方案数。
然后,这个点只可能由三种状态转移而来,即。用将它们累加。
如果说这个点是一个障碍物,那么.
当时,将答案累加即可。
比较有趣的一点是,这道题的时间限制是,众所周知,测评器能跑次循环,而,刚好是的时限。本蒟蒻也是从这里受到了启发。
好了,话不多说,上代码:
#include<iostream>
#include<map>
using namespace std;
#define int long long
const int N=305,mod=998244353,base=1e9;
int n,m,a,b,c,d,e,F;
int f[N][N][N],ans;
int x,y;
map<int,bool>mp;
inline int get_point(int x,int y){
return (x-1)*base+y;
}
signed main(){
cin>>n>>m>>a>>b>>c>>d>>e>>F;
for(int i=1;i<=m;i++) cin>>x>>y,mp[get_point(x,y)]=1;//坐标很大,我们可以将二维坐标一维化,然后用map存储
f[0][0][0]=1;//初始在(0,0)的位置,所以
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++){
if(i+j>n) break;
for(int k=0;k<=n;k++){
if(i+j+k>n) break; //玄学优化
if(i==0&&j==0&&k==0) continue; //起始点不用更新
int gx=i*a+j*c+k*e;
int gy=i*b+j*d+k*F;
if(mp[get_point(gx,gy)]) {f[i][j][k]=0;continue;} //障碍物
if(i) f[i][j][k]=(f[i][j][k]+f[i-1][j][k])%mod;
if(j) f[i][j][k]=(f[i][j][k]+f[i][j-1][k])%mod;
if(k) f[i][j][k]=(f[i][j][k]+f[i][j][k-1])%mod;
//一定要注意是否为0,不然数组可能会越界
if(i+j+k==n) ans=(ans+f[i][j][k])%mod;
}
}
cout<<ans;
//跑出来刚好2700ms,神不神奇呢
}
完结撒花~~~