noi2005<瑰丽华尔兹>

链接:https://www.luogu.org/problemnew/show/P2254

题解:

思路很好想,若用f[i][j][k]表示k时间到达i,j位置的最大花费 转移即从当前方向转移

时间复杂度(n*m*t) 空间复杂度(n*m*t)

注意到题目给出了大T,只有200,n*m*T的时间是可以接受的

容易发现f[i][j][k]可以由一段t时刻转移而来,而这个可以由单调队列做到o(1)修改

另外由于可以不动,所以当t2>t1时,t2状态一定优于t1,时间这一维在数组中可以省略

注意:分4种情况讨论的单调队列不是很好调试,要背清楚模板

单调队列模板:

#include <btis/stdc++.h>
using namespace std;
int h,t;
void insert(int x,int y)
{
     for (int i=t;i>=h;i--)
       if (条件) break;
     q[++i]=y; id[++i]=x; 
} 
int main()
{
    h=1,t=0;{队列的头要在开始处}
    for (int i=1;i<=n;i++)
    {
        if (h<=t&&id[h]+x<i) h++;{要保证元素不为空} 
        //更新
        insert(i,值); 
    }
}
View Code

 这道题中的单调队列还需要做一些处理

方程f[i][j]=max{f[i-k][j]+k}; 我们可以在加入单调队列时对每个元素-j,那么比较时就是等价的,最后再加上j就可以了

这是一种基本的dp优化

代码:

#include <bits/stdc++.h>
using namespace std;
int n,m,x,y,k;
char c;
const int maxn=500;
bool f[maxn][maxn];
int q[maxn],len[maxn],id[maxn],p[maxn],h,t,dp[maxn][maxn],hh[maxn],tt[maxn],fx[maxn];
void insert(int x,int y)
{
    int i;
    for (i=t;i>=h;i--)
    {
        if (y<p[i]) break;
    }
    p[++i]=y; t=i;
    id[i]=x;
}
int main()
{
    freopen("noip.in","r",stdin);
    freopen("noip.out","w",stdout);
    cin>>n>>m>>x>>y>>k;
    memset(f,true,sizeof(f));
    for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
      {
          cin>>c;
          if (c=='x') f[i][j]=false;
        }
    for (int i=1;i<=k;i++)
    {
        cin>>hh[i]>>tt[i]>>fx[i];
        len[i]=tt[i]-hh[i]+1;
    }
    memset(dp,-1,sizeof(dp));
    dp[x][y]=0;
  for (int i=1;i<=k;i++)
    {
        if (fx[i]==3)
        {
            for (int j1=1;j1<=n;j1++)
            {
                h=1;t=0;
              for (int j2=m;j2>=1;j2--)
              {
                  if (id[h]-len[i]>j2&&h<=t) h++;
                  if (f[j1][j2]!=0)
                  {
                      int tmp=dp[j1][j2];
                      if (h<=t)
                      { 
                        int x=h;
                        dp[j1][j2]=max(dp[j1][j2],p[x]+m-j2);
                      } 
                      if (tmp!=-1) insert(j2,tmp-(m-j2));
                    } else
                    {
                        h=1;t=0;
                    }
                }
          }
        }
                if (fx[i]==4)
        {
            for (int j1=1;j1<=n;j1++)
            {
                h=1;t=0;
                for (int j2=1;j2<=m;j2++)
              {
                  if (id[h]+len[i]<j2&&h<=t) h++;
                  if (f[j1][j2]!=0)
                  {
                      int tmp=dp[j1][j2];
                      if (h<=t)
                      { 
                        int x=h;
                        dp[j1][j2]=max(dp[j1][j2],p[x]+j2);
                      } 
                      if (tmp!=-1) insert(j2,tmp-j2);
                    } else
                    {
                        h=1;t=0;
                    }
                }
          }
        }
                if (fx[i]==1)
        {
            for (int j1=1;j1<=m;j1++)
            {
                h=1;t=0;
              for (int j2=n;j2>=1;j2--)
              {
                  if (id[h]-len[i]>j2&&h<=t) h++;
                  if (f[j2][j1]!=0)
                  {
                      int tmp=dp[j2][j1];
                      if (h<=t)
                      { 
                        int x=h;
                        dp[j2][j1]=max(dp[j2][j1],p[x]+n-j2);
                      } 
                      if (tmp!=-1) insert(j2,tmp-(n-j2));
                    } else
                    {
                        h=1;t=0;
                    }
                }
          }
        }
                if (fx[i]==2)
        {
            for (int j1=1;j1<=m;j1++)
            {
                h=1;t=0;
              for (int j2=1;j2<=n;j2++)
              {
                  if (id[h]+len[i]<j2&&h<=t) h++;
                  if (f[j2][j1]!=0)
                  {
                      int tmp=dp[j2][j1];
                      if (h<=t)
                      { 
                        int x=h;
                        dp[j2][j1]=max(dp[j2][j1],p[x]+j2);
                      } 
                      if (tmp!=-1) insert(j2,tmp-j2);
                    } else
                    {
                        h=1;t=0;
                    }
                }
          }
        }
    } 
    int ans=-1;
    for (int i=1;i<=n;i++)
    {
      for (int j=1;j<=m;j++)
      {
          ans=max(ans,dp[i][j]);
        }
   }
    cout<<ans;
}
View Code

 

posted @ 2018-01-30 15:07  尹吴潇  阅读(131)  评论(0编辑  收藏  举报