#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 ...
随机推荐
- 【[HNOI2015]亚瑟王】
神仙题,抄题解 用\(tp_i\)表示\(i\)这个技能在\(r\)轮中被使用过的概率 于是最后的答案就是\(\sum_{i=1}^nd_i*tp_i\) 首先\(tp_1=1-(1-p_1)^r\) ...
- webpack中热模块更新
Hot Module Replacement,热模块更新,很多时候会简写成HMR. "scripts": { "start": "webpack-de ...
- 【QT】QString类型转换为const char*(toLatin1)
Qstring str = "helloworld"; char *s; QByteArray ba = str.toLatin1(); s = ba.data(); toLati ...
- 随手练——HDU 1251 统计难题
知识点:前缀树.典型的前缀树模板. 这是用next[26]数组的版本,超内存了.(后来发现,用C++交不会超,G++就会超) #include <iostream> #include &l ...
- MyBatis(3)-映射文件
本次博文有疑问,请先看MyBatis(1)-简单入门 和 MyBatis(2)-全局配置文件! 如在有疑问,请留言或者咨询博主,博主每天都在!谢谢! 映射文件: 主要是在xxxmapper.xml文件 ...
- 在Windows 10中更改网络连接优先级
查看接口列表 (也可使用 如下) 选择网络连接,然后单击右侧的箭头以更改网络连接优先级. 可以参考之前的部分 链接在此 更改单个wi-fi连接顺序可以使用如下
- PHPStorm自定义主题配置
1.下载喜欢的主题 官方下载地址:下载 2.将.icls主题文件放到PHPStorm的配置中 windows下主题位置:C:\Users\Administrator\.PhpStorm2017.3\c ...
- 求1!+2!+3!+4!+5!+6!+7!+8!+9!+10!+...+N! N阶阶乘求和算法 JAVA C Python
一行代码算出1!+2!+3!+4!+5!+6!+7!+8!+9!+10!+...+N! N阶阶乘求和 时间复杂度为O(n) 空间复杂度为O(1) 对于任意正整数N 求1!-N!一行算出和给定求1 ...
- oracle中的greatest 函数和 least函数
oracle中的greatest 函数和 least函数 原文地址:https://blog.csdn.net/sinat_32023305/article/details/78778596 g ...
- Oracle与MySQL使用区别
与MySQL通过创建不同的数据库来存储表 Oracle提出表空间(tablespace)的概念作为逻辑上的存储区域来存储表, 而不同的表空间由不同的用户来管理 用户可以授予权限或角色 举例: 使用PL ...