zoukankan      html  css  js  c++  java
  • Luogu P3638 [APIO2013]机器人

    (类似)斯坦纳树+DP

    (f[l][r][i][j]) 表示已经构成 ([l,r]) 的机器人,并在点 ((i,j)) 的最小代价。

    预处理出 (d[i][j][k]) 表示在点 ((i,j)) 方向为 (k) 时最终能够到达的点。

    (f[l][r][i][j]=min(f[l][k][i][j],f[k+1][r][i][j]))

    (枚举k,f[l][r][X][Y]=min(f[l][r][X][Y],f[l][r][i][j]+1),(X,Y)表示(i,j,k)最终到达的点)

    spfa 要优化:用两个队列,一个存初始状态(先排完序再扔进去),一个存扩展出来的状态,每次取两个队头中较小的去扩展。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<cstring>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } const int N=10,M=510,Inf=0x3f3f3f3f;
    const int dx[]={-1,0,1,0},dy[]={0,-1,0,1};
    struct node { int x,y,dis;
    	inline bool operator < (const node& that) const 
    		{return dis<that.dis;}
    };
    int n,h,w,ans=Inf;
    int d[M][M][4],f[N][N][M][M];
    char s[M][M];
    bool vis[M][M][4],inq[M][M];
    #define P(i,j) ((i-1)*w+j)
    inline int dfs(int i,int j,int k) {
      if(i<1||i>h||j<1||j>w) return 0;
      if(s[i][j]=='x') return 0;
      if(d[i][j][k]) return d[i][j][k];
      if(vis[i][j][k]) return -1;
      vis[i][j][k]=true; R K=k;
      if(s[i][j]=='A') K=(k+1)%4;
      if(s[i][j]=='C') K=(k+3)%4;
    	d[i][j][k]=dfs(i+dx[K],j+dy[K],K);
      if(!d[i][j][k]) d[i][j][k]=P(i,j);
      vis[i][j][k]=false;
      return d[i][j][k];
    }
    queue<node> q1,q2;
    vector<node> mem;
    inline void main() {
      n=g(),w=g(),h=g();
      for(R i=1;i<=h;++i) scanf("%s",s[i]+1);
      for(R i=1;i<=h;++i) for(R j=1;j<=w;++j)
        for(R k=0;k<4;++k) d[i][j][k]=dfs(i,j,k);
      memset(f,0x3f,sizeof f);
      for(R i=1;i<=h;++i) for(R j=1;j<=w;++j) 
        if(isdigit(s[i][j])) 
          f[s[i][j]-'0'][s[i][j]-'0'][i][j]=0;
      for(R l=n;l>=1;--l) for(R r=l;r<=n;++r) {
        for(R i=1;i<=h;++i) for(R j=1;j<=w;++j) for(R k=l;k<r;++k) 
          f[l][r][i][j]=min(f[l][r][i][j],f[l][k][i][j]+f[k+1][r][i][j]);
        for(R i=1;i<=h;++i) for(R j=1;j<=w;++j)
          if(f[l][r][i][j]!=Inf) 
            mem.push_back((node){i,j,f[l][r][i][j]}),inq[i][j]=true;
        sort(mem.begin(),mem.end());
        for(const auto& v:mem) q1.push(v); mem.clear();
        while(q1.size()||q2.size()) {
          R x,y;
          if(q1.size()) {
            if(q2.size()) {
              if(f[l][r][q1.front().x][q1.front().y]<f[l][r][q2.front().x][q2.front().y]) 
                x=q1.front().x,y=q1.front().y,q1.pop();
              else 
                x=q2.front().x,y=q2.front().y,q2.pop();
            } else 
            		x=q1.front().x,y=q1.front().y,q1.pop();
          } 
    			else x=q2.front().x,y=q2.front().y,q2.pop();
    			inq[x][y]=false;
          for(R k=0;k<4;++k) {
            R xx=(d[x][y][k]-1)/w+1,yy=(d[x][y][k]-1)%w+1;
            if(f[l][r][xx][yy]>f[l][r][x][y]+1) {
              f[l][r][xx][yy]=f[l][r][x][y]+1;
              if(!inq[xx][yy]) {
                q2.push((node){xx,yy,f[l][r][xx][yy]});
                inq[xx][yy]=true;
              }
            }
          }
        }
      }
      for(R i=1;i<=h;++i) for(R j=1;j<=w;++j)
        ans=min(ans,f[1][n][i][j]);
      if(ans==Inf) puts("-1");
      else printf("%d
    ",ans);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2020.01.18

  • 相关阅读:
    C# 设计模式-状态模式
    C# 设计模式-备忘录模式
    C# 设计模式-命令模式
    本地易优安装总结
    视频自动添加字幕
    百度商桥安装
    百度统计
    模板
    百度地图API
    栅格布局的理解
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12209865.html
Copyright © 2011-2022 走看看