NC214320. 迷路の小L
描述
输入描述
输入共行。
第一行包含个正整数和个非负整数。
接下来行,每行包含个非负整数,其中第行第个数表示。
接下来行,第行包含一个非负整数。
输出描述
输出共行,第行包含一个正整数,表示对于第次询问,小最多能跑过的点数。
示例1
输入:
5 5 1 1 1 10 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 3
输出:
8
说明:
。示例2
输入:
5 5 1 3 1 10 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1 0 0 0 1 1 1 0 0 0 10
输出:
1
说明:
很遗憾,但小不能跑。注意,在同一点内多次改变方向时,该点并不会被重复计数,因为小不能用转圈代替跑步。C++(clang++11) 解法, 执行用时: 163ms, 内存消耗: 133112K, 提交时间: 2021-02-03 20:36:56
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f3f3f3f3fll const int N=1005; typedef long long ll; int n,m,s,tot,T,p,q,a[N][N]; int dx[]={1,-1,0,0}; int dy[]={0,0,1,-1}; int vis[N][N],num,head[4*N],nex[N*N],to[N*N],wi[N*N]; ll f[4*N][4*N],mx[4*N]; void add(int u,int v,int w){to[++num]=v;nex[num]=head[u];head[u]=num;wi[num]=w;} void go(int x,int y) { for(int i=0;i<4;i++) { int xx=x,yy=y; while(!a[xx+dx[i]][yy+dy[i]]) xx+=dx[i],yy+=dy[i]; if(xx==x&&yy==y) continue; if(!vis[xx][yy]) { vis[xx][yy]=++tot; go(xx,yy); } add(vis[x][y],vis[xx][yy],abs(x-xx)+abs(y-yy)); } } int main() { scanf("%d%d%d%d%d%d",&n,&m,&T,&p,&q,&s); for(int i=0;i<=n+1;i++) for(int j=0;j<=m+1;j++) a[i][j]=1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); vis[p][q]=++tot; go(p,q); assert(tot<=4000); memset(f,-inf,sizeof(f)); f[1][0]=0; for(int i=0;i<=tot;i++) for(int j=1;j<=tot;j++) { if(f[j][i]==f[0][0]) continue; for(int k=head[j];k;k=nex[k]) { int v=to[k]; f[v][i+1]=max(f[v][i+1],f[j][i]+wi[k]); } } for(int i=1;i<=tot;i++) for(int j=head[i];j;j=nex[j]) mx[i]=max(mx[i],1ll*wi[j]); while(T--) { int k;scanf("%d",&k);k++; ll ans=0; for(int i=1;i<=tot;i++) { if(k<=tot) ans=max(ans,f[i][k]); else ans=max(ans,f[i][tot]+(k-tot)*mx[i]); } printf("%lld\n",ans+1); } }