【洛谷P3959】 宝藏

宝藏

题目链接

 

本来是刷状压dp的,然而不会。。

愤怒的小鸟

 

首先,打了一个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\n",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();
    }
};
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\n",ans);
    return 0;
}

不断改种子,提交17次,O2优化,终于卡了过去(%Ha

(状压dp什么的。。61吧。。

猜你喜欢

转载自www.cnblogs.com/yjkhhh/p/9296633.html