zoukankan      html  css  js  c++  java
  • 洛谷2254 BZOJ1499 瑰丽华尔兹题解

    洛谷链接

    BZ链接

    一个很容易想到的做法就是用f[i][j][t]表示t时刻在i,j处的可以滑动的最大值

    f[i][j][t]=max(f[i][j][t-1],f[*i][*j][t-1]),这样大力转移

    只不过会TLE+MLE

    所以我们要进行一下优化

    f[i][j][k]表示在第k个时间段在i,j处的可以滑动的最大值

    f[i][j][k]=max(f[*i][*j][k-1]+dis(i,j,*i,*j,f[i][j][k-1])

    //*i,*j表示上一个合理的位置

    注意到我们的i,与*i,以及j与*j一定有一个相等,即它们在同一行或者同一列

    所以我们可以根据滑动的路径一行一行或者一列一列进行转移

    而这个位置的可以转移来的位置即是它向前len长度的之内的位置

    这与滑动窗口很类似,可以用单调队列来维护max(f[*i][*j][k-1])

    然后在考虑障碍,我们发现一旦遇到障碍,之前的答案都不能转移过来

    所以在有障碍是清空队列就好了

    还有一个常规的优化,就是f[i][j][k]仅与f[i][j][k-1]有关,所以可以利用滚动数组进行优化

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    const int mn = 205;
    const int dx[]={0,-1,1,0,0};
    const int dy[]={0,0,0,-1,1};
    struct node{int val,pos;};
    node q[mn];
    node make_node(int x,int y)
    {
        node tmp;tmp.val=x,tmp.pos=y;
        return tmp;
    }
    int n,m,sx,sy,k;
    int dp[mn][mn],ans,d;
    char s[mn];
    bool vis[mn][mn];
    void work(int x,int y,int len)
    {
        int tail=1,head=0;
        for(int i=1;x>=1 && x<=n && y>=1 && y<=m;i++,x+=dx[d],y+=dy[d])
        {
            if(!vis[x][y]) tail=1,head=0;
            else {
               while(tail<=head && q[head].val+i-q[head].pos<=dp[x][y]) head--;
               q[++head] = make_node(dp[x][y],i);//dp[x][y]实际上是dx[x][y][k-1]
           //BZOJ不支持c++11,写成q[++head]=node{dp[x][y],i}会CE
    while(tail<=head && q[head].pos-q[tail].pos>len) tail++; dp[x][y] = q[tail].val+i-q[tail].pos;//现在dp[x][y]才是dp[x][y][k] ans=max(ans,dp[x][y]); } } } int main() { int x,y,z; scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&k); for(int i=1;i<=n;i++) { scanf("%s",s+1); for(int j=1;j<=m;j++) if(s[j]=='.') vis[i][j]=1; else vis[i][j]=0; } memset(dp,0xf3,sizeof(dp)); dp[sx][sy]=0; for(int i=1;i<=k;i++) { scanf("%d%d%d",&x,&y,&d); if(d==1) for(int j=1;j<=m;j++) work(n,j,y-x+1); if(d==2) for(int j=1;j<=m;j++) work(1,j,y-x+1); if(d==3) for(int j=1;j<=n;j++) work(j,m,y-x+1); if(d==4) for(int j=1;j<=n;j++) work(j,1,y-x+1); } printf("%d",ans); return 0; }
  • 相关阅读:
    【leetcode】1365. How Many Numbers Are Smaller Than the Current Number
    【leetcode】1363. Largest Multiple of Three
    【leetcode】1362. Closest Divisors
    【leetcode】1361. Validate Binary Tree Nodes
    【leetcode】1360. Number of Days Between Two Dates
    【leetcode】1359. Count All Valid Pickup and Delivery Options
    【leetcode】1357. Apply Discount Every n Orders
    【leetcode】1356. Sort Integers by The Number of 1 Bits
    ISE应用入门的一些问题
    DDR的型号问题
  • 原文地址:https://www.cnblogs.com/logeadd/p/9540285.html
Copyright © 2011-2022 走看看