zoukankan      html  css  js  c++  java
  • BZOJ1097 : [POI2007]旅游景点atr

    状压DP新姿势get√

    需要注意的是,这题Main上原题的内存限制只有64MB。

    首先以2到k+1为起点进行k次dijkstra求出:

    1.dis[i][j]:i到j的最短路

    2.d1[i]:i到1的最短路

    3.dn[i]:i到n的最短路

    用二进制状态a[i]表示走到i之前必须经过的点的集合。

    设f[z][S][i]表示现在走过的集合中有z个元素,现在走过的集合为S,最后走过的点是i的最短路,

    则由f[z][S][i]可以向f[z+1][S|(1<<j)][j]扩展,扩展的条件是j不属于S,且S包含a[j]。

    边界条件:f[1][1<<i][i]=a[i]==0?d1[i]:inf

    最后ans=min(f[k][(1<<k)-1][i]+dn[i])

    z这一维显然可以滚动,S这一维最多只有$C_k^{lceilfrac{k}{2} ceil}$种,所以先预处理出:

    1.id[i]:i这个数在与它1的个数相同的数字中排第几

    2.cnt[i]:有i个1的数字个数

    3.st[i][j]:有i个1的数字中排第j的是哪个数

    时间复杂度$O(knlog n+n^2C_k^{lceilfrac{k}{2} ceil})$。

    空间复杂度$O(nC_k^{lceilfrac{k}{2} ceil})$。

    #include<cstdio>
    const int N=20010,M=400010,K=20,Q=184756;
    int n,m,k,i,j,S,E,U,x,y,z,d[N],dis[K][K],d1[K],dn[K],a[K],g[N],v[M],w[M],nxt[M],ed;
    int id[1<<K],cnt[K],st[K][Q],f[2][Q][K],ans=1000000000;
    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 up(int&a,int b){if(a>b)a=b;}
    inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
    struct PI{
      int x,y;
      PI(){}
      PI(int _x,int _y){x=_x,y=_y;}
      inline PI operator+(PI b){return x<b.x?PI(x,y):b;}
    }val[65537];
    void build(int x,int a,int b){
      val[x]=PI(ans,a);
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    inline void change(int x,int a,int b,int c,int d){
      if(a==b){val[x].x=d;return;}
      int mid=(a+b)>>1;
      c<=mid?change(x<<1,a,mid,c,d):change(x<<1|1,mid+1,b,c,d);
      val[x]=val[x<<1]+val[x<<1|1];
    }
    void dijkstra(int S){
      int i;
      for(i=1;i<=n;i++)d[i]=ans;
      build(1,1,n),change(1,1,n,S,d[S]=0);
      while(val[1].x<ans)for(change(1,1,n,x=val[1].y,ans),i=g[x];i;i=nxt[i])if(d[x]+w[i]<d[v[i]])change(1,1,n,v[i],d[v[i]]=d[x]+w[i]);
    }
    int main(){
      read(n),read(m),read(k);
      while(m--)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
      if(!k)return dijkstra(1),printf("%d",d[n]),0;
      for(read(m);m--;a[y-2]|=1<<(x-2))read(x),read(y);
      for(i=2;i<=k+1;i++){
        for(dijkstra(i),j=2;j<=k+1;j++)dis[i-2][j-2]=d[j];
        d1[i-2]=d[1],dn[i-2]=d[n];
      }
      for(E=(1<<k)-1,S=1;S<=E;S++)id[S]=cnt[i=__builtin_popcount(S)-1],st[i][cnt[i]++]=S;
      for(x=0;x<cnt[0];x++)for(i=0;i<k;i++)f[0][x][i]=ans;
      for(i=0;i<k;i++)if(!a[i])f[0][id[1<<i]][i]=d1[i];
      for(z=y=0;z<k-1;z++,y^=1){
        for(x=0;x<cnt[z+1];x++)for(i=0;i<k;i++)f[y^1][x][i]=ans;
        for(x=0;x<cnt[z];x++)for(S=st[z][x],i=0;i<k;i++)if(f[y][x][i]<ans)for(U=E^S;U;U-=U&-U){
          j=__builtin_ctz(U&-U);
          if((S&a[j])==a[j])up(f[y^1][id[S|(1<<j)]][j],f[y][x][i]+dis[i][j]);
        }
      }
      for(i=0;i<k;i++)up(ans,f[y][0][i]+dn[i]);
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    Struts2+Spring3+Mybatis3开发环境搭建
    spring+struts2+mybatis
    【LeetCode】Populating Next Right Pointers in Each Node
    【LeetCode】Remove Duplicates from Sorted Array
    【LeetCode】Remove Duplicates from Sorted Array II
    【LeetCode】Binary Tree Inorder Traversal
    【LeetCode】Merge Two Sorted Lists
    【LeetCode】Reverse Integer
    【LeetCode】Same Tree
    【LeetCode】Maximum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/clrs97/p/4607694.html
Copyright © 2011-2022 走看看