51Nod-1693-水群
2017-08-11 16:48
274 查看
ACM模版
我先说一下这个题怎么解:这个题可以转化为图论,将 i 与 i−1 连边,非要为 1,再将 i 与 i∗k 连边,费用为 k,然后跑一遍最短路。但是因为边数略多,我们需要优化一下,边数多主要是因为 i∗k 的 k 比较多,我们需要将无用的 k 省去。这里我们直接将 k 限定为质数,并且进一步优化是这个 k 不会太大,只要 2,3,5,7,11,13。最短路算法很多,用 spfa 会稍微快一些。
现在我们说一下为什么这么做,首先,我们可以将 i 与 i−1 连边理解为操作三,也就是删除一个表情,然后将 i 连线 i∗k 理解为复制一次,粘贴多次,之所以只考虑这两种情况是因为,多次连续复制无意义,但是复制后多次粘贴是有意义的。那么我们为什么要将 k 限制为质数呢?这个其实挺容易理解的,因为如果 k 是合数,他完全可以由多次代价低的操作组合在一起实现等价的效果,代价总和还是一样的。但是进一步优化就不是那么好理解了,大致的说就是,如果我们将一次复制进行过多次粘贴,他的效果不会比等同代价的更多组复制粘贴组合的效益高,所以我们无需考虑过大的质数情况。没有具体的证明,但是大致上应该是可以理解为什么的,如果不知道控制在多少比较合适,可以自己多卡几组数据试试。另外好像还有一个优化就是连续删除的操作最优不会超过四次,不要问我为什么,这个我也不是特别清楚。大概还是和质数的一些性质有关系吧……
描述
题解
这个题真的很神很神的……我先说一下这个题怎么解:这个题可以转化为图论,将 i 与 i−1 连边,非要为 1,再将 i 与 i∗k 连边,费用为 k,然后跑一遍最短路。但是因为边数略多,我们需要优化一下,边数多主要是因为 i∗k 的 k 比较多,我们需要将无用的 k 省去。这里我们直接将 k 限定为质数,并且进一步优化是这个 k 不会太大,只要 2,3,5,7,11,13。最短路算法很多,用 spfa 会稍微快一些。
现在我们说一下为什么这么做,首先,我们可以将 i 与 i−1 连边理解为操作三,也就是删除一个表情,然后将 i 连线 i∗k 理解为复制一次,粘贴多次,之所以只考虑这两种情况是因为,多次连续复制无意义,但是复制后多次粘贴是有意义的。那么我们为什么要将 k 限制为质数呢?这个其实挺容易理解的,因为如果 k 是合数,他完全可以由多次代价低的操作组合在一起实现等价的效果,代价总和还是一样的。但是进一步优化就不是那么好理解了,大致的说就是,如果我们将一次复制进行过多次粘贴,他的效果不会比等同代价的更多组复制粘贴组合的效益高,所以我们无需考虑过大的质数情况。没有具体的证明,但是大致上应该是可以理解为什么的,如果不知道控制在多少比较合适,可以自己多卡几组数据试试。另外好像还有一个优化就是连续删除的操作最优不会超过四次,不要问我为什么,这个我也不是特别清楚。大概还是和质数的一些性质有关系吧……
代码
#include <queue> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 1e6 + 10; const int MAGIC = 5; int n; int dis[MAXN]; int vis[MAXN]; int prime[] = {6, 2, 3, 5, 7, 11, 13}; int spfa_bfs(int n) { queue<int> q; memset(dis, 0x3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); dis[1] = 0; vis[1] = 1; q.push(1); while (!q.empty()) { int x = q.front(); q.pop(); vis[x] = 0; for (int j = 1; j <= prime[0] && x * prime[j] < n + MAGIC; j++) { int y = x * prime[j], cost = prime[j]; if (dis[x] + cost < dis[y]) { dis[y] = dis[x] + cost; if (!vis[y]) { vis[y] = 1; q.push(y); } } } int y = x - 1, cost = 1; if (dis[x] + cost < dis[y]) { dis[y] = dis[x] + cost; if (!vis[y]) { vis[y] = 1; q.push(y); } } } return dis ; } int main() { scanf("%d", &n); printf("%d\n", spfa_bfs(n)); return 0; }
相关文章推荐
- 51nod 1693 水群(神奇的最短路!)
- 51Nod 1693 水群(打表确定转移范围优化)
- 51nod 1693 水群 (spfa)
- 51NOD_1693 水群
- 51 nod 1693 水群(最短路)
- 1693 水群(最短路)
- 51nod 1086 背包问题 V2(多重背包问题)
- 51nod 1393 0和1相等串 思路 - map存前缀和
- 【51nod】 第K大区间2(二分+树状数组)
- 51Nod-1072-威佐夫游戏
- [51NOD]BSG白山极客挑战赛
- 51nod 1603 限高二叉排列树 计数dp
- 51nod 1134 最长递增子序列
- 51Nod 1335 思维
- 51nod 1035:最长的循环节
- 51Nod 1103 N的倍数
- 51nod 1267 4个数和为0
- 51Nod-1118-机器人走方格
- 51nod 1010 只包含因子2 3 5的数
- 51Nod-1135-原根