#333. 【NOIP2017】宝藏
#333. 【NOIP2017】宝藏
1、错误的$n^42^n$做法:
dp[s]表示当前的点集为s,然后从这些点中选一个做起点i,然后枚举边,然后更新dp[t|(1<<j)]。dis[s][i]表示点集为s的情况下的i号点的深度。详见代码。
为什么是错的,不满足当前最优一定是最后最优。比如下面的hack数据,正确答案应该是10420,即从4号点出发,长度为1的那条边不要。而在上面的dp中,点集为234的状态中只能从24和34转移而来,而这两个取最小值的时候,一定会算上1这条边,答案为12,而不是10这条边。导致下一步dp的时候,深度边长,导致更不优。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<bitset>
using namespace std;
typedef long long LL; //char buf[100000], *p1 = buf, *p2 = buf;
//#define nc() p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++ inline int read() {
int x = , f = ; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch=='-') f = -;
for (; isdigit(ch); ch = getchar()) x = x * + ch - ''; return x * f;
} const int N = ;
const LL LLINF = 1e18;
const int INF = 1e9; LL dp[( << ) + ];
int mp[N][N], dis[( << ) + ][];
int n, m; LL solve(int x) {
memset(dis, , sizeof(dis));
int S = ( << n) - ; for (int s = ; s <= S; ++s) dp[s] = LLINF;
dis[ << x][x] = , dp[ << x] = ; for (int s = , t; s <= S; ++s) { // 点集
if (dp[s] == LLINF) continue;
cout << bitset<>(s) << "\n";
for (int i = ; i < n; ++i) { // 选一个点当起点
if (!((s >> i) & )) continue;
for (int j = ; j < n; ++j) { // 到达的下一个点
if (i == j || mp[i][j] == INF || ((s >> j) & )) continue;
t = s | ( << j);
cout << bitset<>(t) << "\n";
if (dp[t] > dp[s] + dis[s][i] * mp[i][j]) {
dp[t] = dp[s] + dis[s][i] * mp[i][j];
for (int k = ; k < n; ++k) dis[t][k] = dis[s][k];
dis[t][j] = dis[s][i] + ;
cout << dp[t] << "\n";
}
}
}
}
return dp[S];
} int main() {
// freopen("1.txt", "r", stdin);
// freopen("2.txt", "w", stdout);
n = read(), m = read(); for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j) mp[i][j] = INF;
for (int i = ; i <= m; ++i) {
int u = read() - , v = read() - , w = read();
mp[u][v] = min(mp[u][v], w), mp[v][u] = min(mp[v][u], w);
} LL ans = 1e18;
for (int i = ; i < n; ++i)
ans = min(ans, solve(i));
cout << ans; return ;
}
/* hack数据:
dp不满足,当前最优,不满足最后的答案最优 6 14
1 2 101
1 3 44
1 4 235
1 6 629
2 3 60
2 4 196
2 5 250
2 6 490
3 4 237
3 5 114
3 6 715
4 5 166
4 6 432
5 6 932 6 6
1 2 100
2 3 1
2 4 10
3 4 10
3 5 100
4 6 10000 */
2、那么解决上述dp中出现的dp,就需要按深度进行dp,每次枚举下一深度的所有点,子集dp。复杂度$n^33^n$
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<bitset>
using namespace std;
typedef long long LL; inline int read() {
int x = , f = ; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch=='-') f = -;
for (; isdigit(ch); ch = getchar()) x = x * + ch - ''; return x * f;
} const int N = ;
const LL LLINF = 1e18;
const int INF = 1e9; LL dp[( << ) + ][], tmp[( << ) + ], dis[N];
int mp[N][N];
int n, m; LL solve(int x) {
int S = ( << n) - ;
for (int s = ; s <= S; ++s)
for (int i = ; i <= n; ++i) dp[s][i] = LLINF;
dp[ << x][] = ; for (int s = ; s <= S; ++s) {
int r = ;
for (int i = ; i < n; ++i) dis[i] = LLINF;
for (int i = ; i < n; ++i) {
if ((s >> i) & )
for (int j = ; j < n; ++j)
if (!((s >> j) & ) && mp[i][j])
r |= ( << j), dis[j] = min(dis[j], (LL)mp[i][j]);
}
for (int t = r; t; t = (t - ) & r) {
tmp[t] = ;
for (int i = ; i < n; ++i)
if ((t >> i) & ) tmp[t] += dis[i];
}
for (int d = ; d <= n; ++d) {
if (dp[s][d] == LLINF) continue;
for (int t = r; t; t = (t - ) & r)
dp[s | t][d + ] = min(dp[s | t][d + ], dp[s][d] + tmp[t] * d);
}
}
LL ans = LLINF;
for (int i = ; i <= n; ++i) ans = min(ans, dp[S][i]);
return ans;
} int main() { n = read(), m = read(); for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j) mp[i][j] = INF;
for (int i = ; i <= m; ++i) {
int u = read() - , v = read() - , w = read();
mp[u][v] = min(mp[u][v], w), mp[v][u] = min(mp[v][u], w);
} LL ans = 1e18;
for (int i = ; i < n; ++i)
ans = min(ans, solve(i));
cout << ans; return ;
}
3、随机化算法
#333. 【NOIP2017】宝藏的更多相关文章
- 【比赛】NOIP2017 宝藏
这道题考试的时候就骗了部分分.其实一眼看过去,n范围12,就知道是状压,但是不知道怎么状压,想了5分钟想不出来就枪毙了状压,与AC再见了. 现在写的是状压搜索,其实算是哈希搜索,感觉状压DP理解不了啊 ...
- [NOIP2017]宝藏 状压DP
[NOIP2017]宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖 ...
- [NOIP2017]宝藏 子集DP
题面:[NOIP2017]宝藏 题面: 首先我们观察到,如果直接DP,因为每次转移的代价受上一个状态到底选了哪些边的影响,因此无法直接转移. 所以我们考虑分层DP,即每次强制现在加入的点的距离为k(可 ...
- NOIP2017宝藏 [搜索/状压dp]
NOIP2017 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘 ...
- NOIP2017 - 宝藏
LibreOJ链接 Description 给出一个\(n(n\leq12)\)个点\(m(m\leq1000)\)条边的带权无向图,求该图的一棵生成树,使得其边权×该边距根的深度之和最小. Solu ...
- Luogu 3959 [NOIP2017] 宝藏
NOIP2017最后一道题 挺难想的状压dp. 受到深度的条件限制,所以一般的状态设计带有后效性,这时候考虑把深度作为一维,这样子可以保证所有状态不重复计算一遍. 神仙预处理:先处理出一个点连到一个集 ...
- 洛谷P3959 [NOIP2017]宝藏
[题目描述] 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋,也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但 ...
- NOIP2017 宝藏 题解报告【状压dp】
题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是 ...
- 【洛谷P3959】[NOIP2017] 宝藏
宝藏 题目链接 首先,打了一个prim,得了45分 #include<iostream> #include<cstring> #include<cstdio> #i ...
- [NOIP2017] 宝藏 【树形DP】【状压DP】
题目分析: 这个做法不是最优的,想找最优解请关闭这篇博客. 首先容易想到用$f[i][S][j]$表示点$i$为根,考虑$S$这些点,$i$的深度为$j$情况的答案. 转移如下: $f[i][S][j ...
随机推荐
- 快速搭建redis单机版和redis集群版
单机版 第一步:需要安装redis所需的C语言环境,若虚拟机联网,则执行 yum install gcc-c++ 第二步:redis的源码包上传到linux系统 第三步:解压缩redis tar ...
- 1968. [AHOI2005]约数研究【数论】
Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input ...
- [19/04/15-星期一] 基于Socket(套接字)的TCP和UDP通讯的实现
一.TCP 在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序,简称客户端,而在第一次通讯中等待连接的程序被称作服务器端(Server)程序, 简称服务器.一旦通讯建立,则客户端和 ...
- HDU 1686 Oulipo (可重叠匹配 KMP)
Oulipo Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- 怎样实现一个简单的jQuery编程
第一步:在head中载入jQuery框架 <script type="text/javascript" src="jQuery文档所在的绝对路径"> ...
- Caused by: java.lang.ClassNotFoundException: org.springframework.boot.bind.RelaxedPropertyResolver
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.bind.RelaxedPropertyResolver 这 ...
- list 去重复元素
public static List removeDuplicate(List list){ List listTemp = new ArrayList(); for(int i=0;i<lis ...
- 【js】 ajax 与 axios 区别
ajax 与 axios区别 Ajax: Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发 ...
- C++较精确的测试代码运行时间
#include <chrono> using namespace chrono; int main() { auto t0 = system_clock::now(); //测试代码 a ...
- 【PTA 天梯赛】L2-028 秀恩爱分得快(模拟)
古人云:秀恩爱,分得快. 互联网上每天都有大量人发布大量照片,我们通过分析这些照片,可以分析人与人之间的亲密度.如果一张照片上出现了 K 个人,这些人两两间的亲密度就被定义为 1/K.任意两个人如果同 ...