zoukankan      html  css  js  c++  java
  • NOIp2017D2T2(luogu3959) 宝藏 (状压dp)

    时隔多年终于把这道题过了

    数据范围显然用搜索剪枝状压dp。

    可以记还有哪些点没到(或者已到了哪些点)、我们最深已到的是哪些点、这些点的深度是多少,然后一层一层地往下推。

    但其实是没必要记最深的那一层的,只要强行装作每次更新都是用最深的深度更新就可以。这样的话,虽然会有很多情况偏大,但是能正确更新的情况其实是都已经包括了。

    因为你如果想以当前状态去更新,但用的还不是最深一层的点的话,干脆就可以在之前你想用那个点处于最后一层的时候去更新。

    代码写的很捉急..最后常数也很捉急...

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 #include<cmath>
     7 #include<ctime>
     8 #define LL long long int
     9 #define inf 0x3f3f3f3f
    10 using namespace std;
    11 const int maxs=5000,maxn=15,maxm=1010;
    12 
    13 LL rd(){
    14    LL x=0;char c=getchar();int neg=1;
    15    while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    16    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    17    return x*neg;
    18 }
    19 
    20 int eg[maxm*2][3],egh[maxn],ect;
    21 int f[maxn][maxs],dis0[maxs][maxn],dis[maxs][maxs],bin[maxn];
    22 int N,M;
    23 
    24 inline void adeg(int a,int b,int v){
    25     eg[ect][0]=b;eg[ect][1]=egh[a];eg[ect][2]=v;egh[a]=ect++;
    26     for(int i=1;i<bin[N+1];i++) if((bin[a]&i) && !(bin[b]&i)) dis0[i][b]=min(dis0[i][b],v);
    27 }
    28 
    29 void dfs(int x,int y,int s,int e){
    30     if(x>N) dis[s][e]=y;
    31     else{
    32         if(dis0[s][x]<=500000) dfs(x+1,y+dis0[s][x],s,e|bin[x]);
    33         dfs(x+1,y,s,e);
    34     }
    35 }
    36 
    37 int main(){
    38     int i,j,k;
    39     N=rd(),M=rd();
    40     memset(egh,-1,sizeof(egh));memset(dis,127,sizeof(dis));
    41     memset(dis0,127,sizeof(dis0));memset(f,127,sizeof(f));
    42     for(i=1,j=1;i<=N+1;i++,j<<=1) bin[i]=j;
    43     for(i=1;i<=M;i++){
    44         int a=rd(),b=rd(),c=rd();
    45         adeg(a,b,c);adeg(b,a,c);
    46     }
    47     for(i=1;i<bin[N+1];i++) dfs(1,0,i,0);
    48     for(i=1;i<=N;i++) f[1][bin[i]]=0;
    49     for(i=1;i<N;i++){
    50         for(j=1;j<bin[N+1];j++){
    51             if(f[i][j]>=9e7) continue;
    52             for(k=1;k<bin[N+1];k++){
    53                 if(dis[j][k]>500000) continue;
    54                 f[i+1][j|k]=min(f[i+1][j|k],f[i][j]+i*dis[j][k]);
    55             }
    56         }
    57     }int ans=0x3f3f3f3f;
    58     for(i=1;i<=N;i++) ans=min(f[i][(1<<N)-1],ans);
    59     printf("%d
    ",ans);
    60     return 0;
    61 }
  • 相关阅读:
    Firefly 3288又一次制作android和lubuntu双系统固件
    想做一个完美的健身训练计划,你须要知道什么?
    【LeetCode-面试算法经典-Java实现】【075-Sort Colors (颜色排序)】
    每天进步一点点——Ganglia的Python扩展模块开发
    Unity3D-rigidBody.velocity
    泛型初识
    HDOJ 5418 Victor and World 状压DP
    UIPopoverController具体解释
    怎样提升站点的性能?
    PHP操作MongoDB数据库具体样例介绍(增、删、改、查) (六)
  • 原文地址:https://www.cnblogs.com/Ressed/p/9588395.html
Copyright © 2011-2022 走看看