• BZOJ4356 : Ceoi2014 Wall


    求出左上角到每个需要保护的点左上角的最短路树,那么最优解一定圈住了它们。

    然后将每个点拆成四个点,四个点之间如果没跨越最短路树的树边,那就连0权边。

    每个需要保护的点四周4个点都不可通行,求出最短路即为答案。

    时间复杂度$O(nmlog(nm))$。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,int>P;
    const int N=410,M=2600000;
    const ll inf=1LL<<60;
    int n,m,i,j,k,x,y,a[N][N],b[N][N],c[N][N];
    int tot,f[N][N],X[N*N],Y[N*N],pre[N][N];
    ll d[N][N];
    bool vis[N][N],mark[N][N][4],del[N*N*4];
    priority_queue<P,vector<P>,greater<P> >Q;
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void ext(int x,int y,ll z,int p){
      if(!f[x][y]||d[x][y]<=z)return;
      d[x][y]=z,pre[x][y]=p;
      Q.push(P(z,f[x][y]));
    }
    void dfs(int x,int y){
      if(x==1&&y==1)return;
      if(vis[x][y])return;
      vis[x][y]=1;
      int X=x,Y=y,D=pre[x][y];
      mark[x][y][D]=1;
      if(!D)X--;
      if(D==1)X++;
      if(D==2)Y--;
      if(D==3)Y++;
      mark[X][Y][D^1]=1;
      dfs(X,Y);
    }
    namespace G{
    int f[N][N][4],X[N*N*4],Y[N*N*4],Z[N*N*4];
    int g[N*N*4],v[M],w[M],nxt[M],ed;
    ll d[N*N*4];
    inline void add(int x,int y,int z){
      if(del[x]||del[y])return;
      v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;
      v[++ed]=x;w[ed]=z;nxt[ed]=g[y];g[y]=ed;
    }
    void work(){
      Q.push(P(d[2]=0,2));
      while(!Q.empty()){
        P t=Q.top();Q.pop();
        if(d[x=t.second]<t.first)continue;
        for(i=g[x];i;i=nxt[i])if(d[x]+w[i]<d[v[i]])Q.push(P(d[v[i]]=d[x]+w[i],v[i]));
      }
      printf("%lld",d[3]);
    }
    }
    int main(){
      read(n),read(m);
      for(i=1;i<=n;i++)for(j=1;j<=m;j++)read(a[i][j]);
      for(i=1;i<=n;i++)for(j=1;j<=m+1;j++)read(b[i][j]);
      for(i=1;i<=n+1;i++)for(j=1;j<=m;j++)read(c[i][j]);
      for(i=1;i<=n+1;i++)for(j=1;j<=m+1;j++)f[i][j]=++tot,d[i][j]=inf,X[tot]=i,Y[tot]=j;
      Q.push(P(d[1][1]=0,1));
      while(!Q.empty()){
        P t=Q.top();Q.pop();
        if(d[x=X[t.second]][y=Y[t.second]]<t.first)continue;
        ext(x+1,y,d[x][y]+b[x][y],0);
        ext(x-1,y,d[x][y]+b[x-1][y],1);
        ext(x,y+1,d[x][y]+c[x][y],2);
        ext(x,y-1,d[x][y]+c[x][y-1],3);
      }
      for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(a[i][j])dfs(i,j);
      for(tot=0,i=1;i<=n+1;i++)for(j=1;j<=m+1;j++)for(k=0;k<4;k++){
        G::f[i][j][k]=++tot,G::X[tot]=i,G::Y[tot]=j,G::Z[tot]=k;
        G::d[tot]=inf;
      }
      for(del[1]=i=1;i<=n;i++)for(j=1;j<=m;j++)if(a[i][j]){
        del[G::f[i][j][3]]=1;
        del[G::f[i+1][j][1]]=1;
        del[G::f[i][j+1][2]]=1;
        del[G::f[i+1][j+1][0]]=1;
      }
      for(i=1;i<=n;i++)for(j=1;j<=m+1;j++){
        G::add(G::f[i][j][2],G::f[i+1][j][0],b[i][j]);
        G::add(G::f[i][j][3],G::f[i+1][j][1],b[i][j]);
      }
      for(i=1;i<=n+1;i++)for(j=1;j<=m;j++){
        G::add(G::f[i][j][1],G::f[i][j+1][0],c[i][j]);
        G::add(G::f[i][j][3],G::f[i][j+1][2],c[i][j]);
      }
      for(i=1;i<=n+1;i++)for(j=1;j<=m+1;j++){
        if(!mark[i][j][0])G::add(G::f[i][j][0],G::f[i][j][1],0);
        if(!mark[i][j][1])G::add(G::f[i][j][2],G::f[i][j][3],0);
        if(!mark[i][j][2])G::add(G::f[i][j][0],G::f[i][j][2],0);
        if(!mark[i][j][3])G::add(G::f[i][j][1],G::f[i][j][3],0);
      }
      G::work();
      return 0;
    }
    

      

  • 相关阅读:
    正则表达式,re模块
    序列化(pickle,shelve,json,configparser)
    unity 模型 材质 贴图 关系;着色器属性
    Unity 控制public/private 是否暴露给Inspector面板
    Unity局部坐标系与世界坐标系的区别
    Unity脚本中可以引用的类型
    Unity 脚本挂载位置
    Unity 获取坐标函数 坐标转换函数
    Unity 烘焙的2种方式
    Unity官方宣传片Adam 播放地址
  • 原文地址:https://www.cnblogs.com/clrs97/p/5196611.html
Copyright © 2020-2023  润新知