• 【比赛】NOIP2017 宝藏


    这道题考试的时候就骗了部分分。其实一眼看过去,n范围12,就知道是状压,但是不知道怎么状压,想了5分钟想不出来就枪毙了状压,与AC再见了。

    现在写的是状压搜索,其实算是哈希搜索,感觉状压DP理解不了啊。思路来自于Gt,几乎照搬地写了自己的代码。

    思路很简单,搜索。搜索里加了个启发,有点,不,是很像最优性剪枝。

    dfs里,hsh是每个点的深度哈希起来(初始化要对于每一个点定一个专门的哈希值,用这个值来哈希自己的深度),k是已经连上了多少个点,val是代价。

    估价函数里,对于每一个没有加入答案集合的点,找到他连上任意一个集合(可以是答案集合,也可以是以任意一个同样未连上答案集合的点为根的集合,这样的话当前点的深度就为2了)的最小代价。所有代价加起来后就是把剩下所有点加入答案集合的最低要求(不一定是这个值,但一定大于等于这个值),用这个优化dfs。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int MAXN=20,Mod=19260817,inf=0x3f3f3f3f,base=10007;
     5 int n,m,ans,hash[MAXN],f[Mod],G[MAXN][MAXN],d[MAXN];
     6 inline void read(int &x)
     7 {
     8     int data=0,w=1;
     9     char ch=0;
    10     while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    11     if(ch=='-')w=-1,ch=getchar();
    12     while(ch>='0'&&ch<='9')data=(data<<3)+(data<<1)+(ch^'0'),ch=getchar();
    13     x=data*w;
    14 }
    15 inline void init()
    16 {
    17     for(register int i=1;i<=n;++i)
    18         for(register int j=1;j<=n;++j)G[i][j]=inf;
    19     hash[0]=1;
    20     for(register int i=1;i<=n;++i)hash[i]=(ll)hash[i-1]*base%Mod;
    21     for(register int i=0;i<Mod;++i)f[i]=2e9;
    22     ans=2e9;
    23 }
    24 inline int fr()
    25 {
    26     int res=0;
    27     for(register int i=1;i<=n;++i)
    28         if(!d[i])
    29         {
    30             int tmp=inf;
    31             for(register int j=1;j<=n;++j)
    32                 if(G[i][j]!=inf)
    33                 {
    34                     if(d[j])tmp=min(tmp,d[j]*G[i][j]);
    35                     else tmp=min(tmp,2*G[i][j]);
    36                 }
    37             res+=tmp;
    38         }
    39     return res;
    40 }
    41 inline void dfs(int k,int val,int hsh)
    42 {
    43     if(val+fr()>=ans||val>=f[hsh])return ;
    44     f[hsh]=val;
    45     if(k==n)
    46     {
    47         ans=min(ans,val);
    48         return ;
    49     }
    50     for(register int i=1;i<=n;++i)
    51         if(!d[i])
    52             for(register int j=1;j<=n;++j)
    53                 if(d[j]&&G[i][j]!=inf)
    54                 {
    55                     d[i]=d[j]+1;
    56                     dfs(k+1,val+d[j]*G[i][j],(hsh+d[i]*hash[i])%Mod);
    57                     d[i]=0;
    58                 }
    59 }
    60 int main()
    61 {
    62     freopen("treasure.in","r",stdin);
    63     freopen("treasure.out","w",stdout);
    64     read(n);read(m);
    65     init();
    66     for(register int i=1;i<=m;++i)
    67     {
    68         int u,v,k;
    69         read(u);read(v);read(k);
    70         if(u==v)continue;
    71         G[u][v]=min(G[u][v],k);
    72         G[v][u]=min(G[v][u],k);
    73     }
    74     for(register int i=1;i<=n;++i)
    75     {
    76         d[i]=1;
    77         dfs(1,0,hash[i]);
    78         d[i]=0;
    79     }
    80     printf("%d
    ",ans);
    81     return 0;
    82 }
    NOIP2017 宝藏
  • 相关阅读:
    [翻译]Webpack解惑
    Vue.js与angular在数据实现的思考
    多线程入门-第三章-线程的调度与控制之优先级
    多线程入门-第二章-线程的生命周期
    多线程入门-第一章-线程的创建与启动
    多线程入门-概述
    IO流入门-第十三章-File相关
    IO流入门-第十二章-ObjectInputStream_ObjectOutputStream
    IO流入门-第十一章-PrintStream_PrintWriter
    IO流入门-第十章-DataInputStream_DataOutputStream
  • 原文地址:https://www.cnblogs.com/hongyj/p/8075877.html
Copyright © 2020-2023  润新知