zoukankan      html  css  js  c++  java
  • 【洛谷P3959】[NOIP2017] 宝藏

    宝藏

    题目链接

     

    首先,打了一个prim,得了45分

     

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<queue>
     5 using namespace std;
     6 #define N 15
     7 #define M 2000
     8 #define INF 0x3f3f3f3f
     9 int n,m,dis[N],dep[N],ans;
    10 int Head[N],tot;
    11 bool vis[N];
    12 struct NODE{
    13     int to,w,next;
    14 } e[M];
    15 struct cmp{
    16     bool operator()(int a,int b){
    17         return dis[a]>dis[b];
    18     }
    19 };
    20 priority_queue< int , vector<int> , cmp > q;
    21 inline int read(){
    22     int x=0; char c=getchar();
    23     while(c<'0'||c>'9') c=getchar();
    24     while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
    25     return x;
    26 }
    27 inline void add(int x,int y,int w){
    28     e[++tot].to=y;
    29     e[tot].w=w;
    30     e[tot].next=Head[x];
    31     Head[x]=tot;
    32 }
    33 int prim(int St){
    34     int sum=0;
    35     for(int i=1;i<=n;i++){
    36         dis[i]=1000000;
    37         dep[i]=14; vis[i]=0;
    38     }
    39     dis[St]=dep[St]=0;
    40     q.push(St);
    41     while(!q.empty()){
    42         int u=q.top(); q.pop();
    43         if(vis[u]) continue;
    44         vis[u]=1; sum+=dis[u];
    45         for(int i=Head[u];i;i=e[i].next){
    46             int v=e[i].to;
    47              if(dis[v]>(dep[u]+1)*e[i].w){
    48                 dep[v]=dep[u]+1;
    49                 dis[v]=dep[v]*e[i].w;
    50             }
    51             q.push(v);
    52         }
    53     }
    54     return sum;
    55 }
    56 int main()
    57 {
    58     scanf("%d%d",&n,&m);
    59     int x,y,w;
    60     for(int i=1;i<=m;i++){
    61         x=read(); y=read(); w=read();
    62         add(x,y,w); add(y,x,w);
    63     }
    64     ans=INF;
    65     for(int i=1;i<=n;i++)
    66      ans=min(ans,prim(i));
    67     printf("%d
    ",ans);
    68     return 0;
    69 }

    然后看到题解里状压DP、模拟退火什么玩意的。。

    模拟退火我是不会的

    不过随机化什么的好像可以骗一下分

    于是将代码改了一点

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<queue>
    using namespace std;
    #define N 15
    #define M 2000
    #define INF 0x3f3f3f3f
    int n,m,dis[N],dep[N],ans;
    int Head[N],tot;
    bool vis[N];
    struct NODE{
        int to,w,next;
    } e[M];
    struct cmp{
        bool operator()(int a,int b){
            return dis[a]+rand()>dis[b]+rand();  //非常low的随机化
        }
    };
    priority_queue< int , vector<int> , cmp > q;
    inline int read(){
        int x=0; char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
        return x;
    }
    inline void add(int x,int y,int w){
        e[++tot].to=y;
        e[tot].w=w;
        e[tot].next=Head[x];
        Head[x]=tot;
    }
    int prim(int St){
        int sum=0;
        for(int i=1;i<=n;i++){
            dis[i]=1000000;
            dep[i]=14; vis[i]=0;
        }
        dis[St]=dep[St]=0;
        q.push(St);
        while(!q.empty()){
            int u=q.top(); q.pop();
            if(vis[u]) continue;
            vis[u]=1; sum+=dis[u];
            for(int i=Head[u];i;i=e[i].next){
                int v=e[i].to;
                if(vis[v]) continue;
                 if(dis[v]>(dep[u]+1)*e[i].w){
                    dep[v]=dep[u]+1;
                    dis[v]=dep[v]*e[i].w;
                }
                q.push(v);
            }
        }
        return sum;
    }
    int main()
    {
        srand(19260817);
        scanf("%d%d",&n,&m);
        int x,y,w;
        for(int i=1;i<=m;i++){
            x=read(); y=read(); w=read();
            add(x,y,w); add(y,x,w);
        }
        ans=INF;
        int g=200;
        while(g--){
            srand(rand());
            for(int i=1;i<=n;i++)
             ans=min(ans,prim(i));
        }
        printf("%d
    ",ans);
        return 0;
    }

    很迷的是上面代码的复杂度巨大

    然后发现一个很严重的问题

    邻接表就跟吔了shi一样

    我们将邻接表改成邻接矩阵,

    又改了一下随机化的方式

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<queue>
    using namespace std;
    const int MAXN=15,MAXM=2010;
    const int INF=0x3f3f3f3f;
    int n,m,g[MAXN][MAXN];
    int Head[MAXN],num;
    struct NODE{
        int pos,cost;
    };
    struct cmp{
        bool operator ()(NODE a,NODE b){
            return a.cost>b.cost;
        }
    };
    priority_queue< NODE,vector<NODE>,cmp > que;
    bool vis[MAXN];
    NODE s[MAXM];
    int cnt,dis[MAXN],tot[MAXN];
    int prim(int S){
        int ans=0;
        memset(vis,0,sizeof(vis));
        memset(dis,0x3f,sizeof(dis));
        que.push(NODE{S,0});dis[S]=tot[S]=0;
        for(int i=1;i<=n;i++){
            cnt=0;
            while(!que.empty()&&(vis[que.top().pos]||rand()%(i+1)<1)){
                if(!vis[que.top().pos])
                    s[++cnt]=que.top();
                que.pop();
            }
            int k;
            if(que.empty()) k=s[cnt].pos,cnt--; 
            else k=que.top().pos,que.pop();
            vis[k]=1;
            ans+=dis[k];
            if(ans>INF) return INF;
            for(int i=1;i<cnt;i++) que.push(s[i]);
            for(int i=1;i<=n;i++)
             if(g[k][i]<INF){
                if(dis[i]>(tot[k]+1)*g[k][i]){
                    tot[i]=tot[k]+1;
                    dis[i]=tot[i]*g[k][i];
                }
                que.push(NODE{i,dis[i]});
            }
        }
        return ans;
    }
    int main()
    {
        memset(g,0x3f,sizeof(g));
        scanf("%d%d",&n,&m);
        int x,y,w;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&w);
            if(w<g[x][y]) g[x][y]=g[y][x]=w;
        }
        int ans=INF;
        int t=500;
        while(t--)
            for(int i=1;i<=n;i++)
                ans=min(ans,prim(i));
        printf("%d
    ",ans);
        return 0;
    }  

    以上做法都不大靠谱,大家还是状压DP吧(逃

  • 相关阅读:
    DOM优化
    jQuery绑定以及解除时间方法总结,以及事件触发的方法
    javascript的异步编程方法
    innerHTML,innertext ,textcontent,write()
    关于盒子的那些事
    关于HTTP的几种
    关于php中正则匹配包括换行符在内的任意字符的问题总结
    CSS透明属性详解
    Linux下apache日志分析与状态查看方法
    折半排序 (稳定的排序)
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/9296633.html
Copyright © 2011-2022 走看看