• 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;
    }
    

      

  • 相关阅读:
    java的构造方法 java程序员
    No result defined for action cxd.action.QueryAction and result success java程序员
    大学毕业后拉开差距的真正原因 java程序员
    hibernate的回滚 java程序员
    验证码 getOutputStream() has already been called for this response异常的原因和解决方法 java程序员
    浅谈ssh(struts,spring,hibernate三大框架)整合的意义及其精髓 java程序员
    你平静的生活或许会在某个不可预见的时刻被彻底打碎 java程序员
    Spring配置文件中使用ref local与ref bean的区别. 在ApplicationResources.properties文件中,使用<ref bean>与<ref local>方法如下 java程序员
    poj1416Shredding Company
    poj1905Expanding Rods
  • 原文地址:https://www.cnblogs.com/clrs97/p/5196611.html
Copyright © 2020-2023  润新知