【洛谷P3959】[NOIP2017] 宝藏
宝藏
首先,打了一个prim,得了45分
#include<iostream>
#include<cstring>
#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]>dis[b];
}
};
priority_queue< int , vector<int> , cmp > q;
inline int read(){
int x=; char c=getchar();
while(c<''||c>'') c=getchar();
while(''<=c&&c<='') { x=(x<<)+(x<<)+c-''; 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=;
for(int i=;i<=n;i++){
dis[i]=;
dep[i]=; vis[i]=;
}
dis[St]=dep[St]=;
q.push(St);
while(!q.empty()){
int u=q.top(); q.pop();
if(vis[u]) continue;
vis[u]=; sum+=dis[u];
for(int i=Head[u];i;i=e[i].next){
int v=e[i].to;
if(dis[v]>(dep[u]+)*e[i].w){
dep[v]=dep[u]+;
dis[v]=dep[v]*e[i].w;
}
q.push(v);
}
}
return sum;
}
int main()
{
scanf("%d%d",&n,&m);
int x,y,w;
for(int i=;i<=m;i++){
x=read(); y=read(); w=read();
add(x,y,w); add(y,x,w);
}
ans=INF;
for(int i=;i<=n;i++)
ans=min(ans,prim(i));
printf("%d\n",ans);
return ;
}
然后看到题解里状压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=; char c=getchar();
while(c<''||c>'') c=getchar();
while(''<=c&&c<='') { x=(x<<)+(x<<)+c-''; 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=;
for(int i=;i<=n;i++){
dis[i]=;
dep[i]=; vis[i]=;
}
dis[St]=dep[St]=;
q.push(St);
while(!q.empty()){
int u=q.top(); q.pop();
if(vis[u]) continue;
vis[u]=; 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]+)*e[i].w){
dep[v]=dep[u]+;
dis[v]=dep[v]*e[i].w;
}
q.push(v);
}
}
return sum;
}
int main()
{
srand();
scanf("%d%d",&n,&m);
int x,y,w;
for(int i=;i<=m;i++){
x=read(); y=read(); w=read();
add(x,y,w); add(y,x,w);
}
ans=INF;
int g=;
while(g--){
srand(rand());
for(int i=;i<=n;i++)
ans=min(ans,prim(i));
}
printf("%d\n",ans);
return ;
}
很迷的是上面代码的复杂度巨大
然后发现一个很严重的问题
邻接表就跟吔了shi一样
我们将邻接表改成邻接矩阵,
又改了一下随机化的方式
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
using namespace std;
const int MAXN=,MAXM=;
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=;
memset(vis,,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
que.push(NODE{S,});dis[S]=tot[S]=;
for(int i=;i<=n;i++){
cnt=;
while(!que.empty()&&(vis[que.top().pos]||rand()%(i+)<)){
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]=;
ans+=dis[k];
if(ans>INF) return INF;
for(int i=;i<cnt;i++) que.push(s[i]);
for(int i=;i<=n;i++)
if(g[k][i]<INF){
if(dis[i]>(tot[k]+)*g[k][i]){
tot[i]=tot[k]+;
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=;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=;
while(t--)
for(int i=;i<=n;i++)
ans=min(ans,prim(i));
printf("%d\n",ans);
return ;
}
以上做法都不大靠谱,大家还是状压DP吧(逃
【洛谷P3959】[NOIP2017] 宝藏的更多相关文章
- 洛谷P3959 [NOIP2017]宝藏
[题目描述] 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋,也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但 ...
- 洛谷 P3959 NOIP2017 宝藏 —— 状压搜索
题目:https://www.luogu.org/problemnew/show/P3959 搜索: 不是记忆化,而是剪枝: 邻接矩阵存边即可,因为显然没有那么多边. 代码如下: #include&l ...
- 洛谷$P3959\ [NOIp2017]$ 宝藏 状压$dp$
正解:状压$dp$ 解题报告: 传送门$QwQ$ $8102$年的时候就想搞这题了,,,$9102$了$gql$终于开始做这题了$kk$ 发现有意义的状态只有当前选的点集和深度,所以设$f_{i,j} ...
- 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)
洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ...
- 【洛谷P3959】宝藏
题目大意:比较复杂,点 这里 看题. 题解:对于状态压缩 dp 来讲,阶段的确立十分重要.本题中,采用以层次为阶段进行状压 dp. 设状态 \(f[i][S]\) 表示开凿到深度 \(i\),当前已经 ...
- NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
原文链接https://www.cnblogs.com/zhouzhendong/p/9261079.html 题目传送门 - 洛谷P3959 题目传送门 - Vijos P2032 题意 给定一个 ...
- 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)
洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ...
- 洛谷P3959——宝藏
传送门:QAQQAQ 题意: 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了$n$个深埋在地下的宝藏屋, 也给出了这$n$个宝藏屋之间可供开发的$m$条道路和它们的长度. 小明决心亲自前往挖掘所有 ...
- 洛谷 P3959 宝藏 解题报告
P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 \(n\) 个深埋在地下的宝藏屋, 也给出了这 \(n\) 个宝藏屋之间可供开发的 \(m\) 条道路和它们的长度. 小 ...
随机推荐
- C++ Memory System Part2: 自定义new和delete
在第一部分中,我们介绍了new / delete的具体用法和背后的实现细节,这次我们将构建我们自己的小型工具集,可以使用我们自定义的allocator类来创建任意类型的实例(或者实例数组),我们需要做 ...
- linux下memcached的启动/结束的方式
当前项目中,linux下memcached的启动/结束的方式 默认情况下memcached安装到/usr/local/bin下. 进入安装目录,启动memcached:/usr/local/memca ...
- C# this关键字的四种用法(转)
用法一 this代表当前类的实例对象 namespace Demo { public class Test { private string scope = "全局变量"; pu ...
- git打补丁、还原补丁
打补丁.还原补丁 1.两个commit间的修改(包含两个commit,<r1>.<r2>表示两个提交的版本号,<r1>是最近提交) git format-patch ...
- Vue2.0以后,有哪些变化
最近移动端项目版本升级,Vue由之前的1.0升级到2.3,那么,Vue2.0之后,有哪些细节的变化呢,现在总结如下: 1.在每个组件模板,不再支持片段代码 组件中模板: 之前: <templat ...
- React.js学习小结
最近一段时间都在学习React.js,感觉还不错,现在把自己的一些学习笔记记录一下,留着以后学习查看. 0.React全家桶(技术栈) 1.React主体 2.WebPack:grunt.gulp自动 ...
- python 基础 知识
Python Python 是一种强类型 的解释型 动态型语言Python 对象中的不可变 数字,字符串,元组 ,对于不能改变的会创建一个新的 可变 列表 , 字典 ...
- Supper关键字
java中的super关键字是一个引用变量,用于引用直接父类对象. 每当创建子类的实例时,父类的实例被隐式创建,由super关键字引用变量引用. java super关键字的用法如下: super可以 ...
- for循环的几种比较
对一个集合遍历的3种方法:1.for(int i=0;i<list.size();i++) 2.for(int i=0,len=list.size();i<len;i++) 3.for ( ...
- mysql 字符串转换呈毫秒值
SELECT CEIL((UNIX_TIMESTAMP('2011-05-31 23:59:59') - UNIX_TIMESTAMP('2011-05-31 00:59:59'))/1000/60/ ...