1. 程式人生 > >洛谷P2254 [NOI2005]瑰麗華爾茲(單調隊列)

洛谷P2254 [NOI2005]瑰麗華爾茲(單調隊列)

include -- pan har pri 轉移 moto scanf 距離

傳送門

題解

大概就是設$dp[i][x][y]$表示在第$i$個時間段,在$(x,y)$時的最大滑動距離

然後轉移是$dp[i][x][y]=max(dp[i-1][x][y],dp[i][x‘][y‘]+dis(x,y,x‘,y‘))$

然後用單調隊列進行優化,遇到障礙清除整個單調隊列

 1 //minamoto
 2 #include<cstdio>
 3 #include<cstring>
 4 const int N=205;
 5 template<class T>inline bool cmax(T&a,const
T&b){return a<b?a=b,1:0;} 6 int n,m,sx,sy,k,ans,dp[N][N]; 7 int dx[]={0,-1,1,0,0},dy[]={0,0,0,-1,1}; 8 struct node{ 9 int dp,pos; 10 node(int dd=0,int pp=0){dp=dd,pos=pp;} 11 }q[N]; 12 char mp[N][N]; 13 void solve(int x,int y,int len,int d){ 14 int h=1,t=0; 15 for(int i=1;x>=1
&&x<=n&&y>=1&&y<=m;++i,x+=dx[d],y+=dy[d]) 16 if(mp[x][y]==x) h=1,t=0; 17 else{ 18 while(h<=t&&q[t].dp+i-q[t].pos<dp[x][y]) --t; 19 q[++t]=node(dp[x][y],i); 20 if(q[t].pos-q[h].pos>len) ++h; 21 dp[x][y]=q[h].dp+i-q[h].pos;
22 cmax(ans,dp[x][y]); 23 } 24 } 25 int main(){ 26 // freopen("testdata.in","r",stdin); 27 scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&k); 28 for(int i=1;i<=n;++i) scanf("%s",mp[i]+1); 29 memset(dp,0xef,sizeof(dp)); 30 dp[sx][sy]=0; 31 while(k--){ 32 int s,t,d;scanf("%d%d%d",&s,&t,&d); 33 int len=t-s+1; 34 switch(d){ 35 case 1:for(int i=1;i<=m;++i) solve(n,i,len,d);break; 36 case 2:for(int i=1;i<=m;++i) solve(1,i,len,d);break; 37 case 3:for(int i=1;i<=n;++i) solve(i,m,len,d);break; 38 case 4:for(int i=1;i<=n;++i) solve(i,1,len,d);break; 39 } 40 } 41 printf("%d\n",ans); 42 return 0; 43 }

洛谷P2254 [NOI2005]瑰麗華爾茲(單調隊列)