https://www.codechef.com/ZCOPRAC/problems/ZCO13004 似乎交不了题目了,所以没法验证对错,但是同标程的做法是一样的。
题意:
有一块n*m大小的地图,一个人要从(1,1)走到(n,m),只能往右/往下走。但是路上会有很多怪物,这些怪物的位置是B(见下图),第i个怪物从ci时间开始活动,有一个周期di,它在这段时间内的运动轨迹如下图P(a=3,b=2,c=1,d=3)。人不能碰到P,求能否安全到达终点。
t=0 t=1 t=2 t=3
S . . . . S . . . . S . . P . S
. . . . . . . . . P . . . . . .
. B . . . P . . P B P . . B . P
. . . . . . . . . P . . . . . .
t=4 t=5 t=6
. . . . . . . . . P . .
. . . S . P . . . . . .
. P . . P B P S . B . P
. . . . . P . . . . . S
4 4 1 3 2 1 3
YES 6
5 5 2 5 1 1 2 4 4 1 2
YES 8
2 ≤ N,M ≤ 2500.
乍一看好像是一道很难搞的题目,但是由于只能往右/往下走,所以假如到达某个点(i,j),那么到达时间一定是固定的(i+j-2)。所以只要怪物运动到某点的时间有一次和人到达该点的时间(固定值)重合,那么就不能走这个点啦!
最后再随便dp一下就行了。
#include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<stack> #include<string.h> #include<stdlib.h> #include<cstdio> #define ll long long using namespace std; int x[2505][2505]; int dp[2505][2505]; int main(){ int n,m,k,a,b,c,d; cin>>n>>m>>k; for(int i=0;i<k;++i){ cin>>a>>b>>c>>d; int p=c; for(int j=a;j<=min(a+d-1,n);++j){ //向下找 if(j+b-2>=p&&(j+b-2)%p==0) x[j][b]=1; } p=c; for(int j=b;j<=min(b+d-1,m);++j){ //向右找 if(a+j-2>=p&&(a+j-2)%p==0) x[a][j]=1; } p=c; for(int j=a;j>=max(a-d+1,1);--j){ //向上找 if(j+b-2>=p&&(j+b-2)%p==0) x[j][b]=1; } p=c; for(int j=b;j>=max(b-d+1,1);--j){ //向左找 if(a+j-2>=p&&(a+j-2)%p==0) x[a][j]=1; } } for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ if(i==1&&j==1) dp[i][j]=1; if(dp[i-1][j]==1||dp[i][j-1]==1) dp[i][j]=1; } } if(dp[n][m]==1) cout<<"YES"<<endl<<n+m-2<<endl; else cout<<"NO"<<endl; return 0; }