最短路 51Nod1693 水群

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短路 51Nod1693 水群相关的知识,希望对你有一定的参考价值。


传送门:​​点击打开链接​

题意:刚开始只有1个表情,现在有3种操作。操作1.复制,操作2.粘贴,操作3.退格

问要到恰好n个表情,需要的最少的操作数。

思路:这题的思路非常神

首先,我们考虑到把这道题转换成图论,i与i-1之间连一条边,费用为1,i与i*k之间连一条边,费用为k,然后跑一遍最短路。

但是,这里的边数太大了,这里就出现了我们第一个优化,这个优化我觉得值得我们思考。。

在连接i与i*k的边时,只连接k为质数时的点。很容易发现这样是正确的

这也给我们打开了思路,以后遇到乘法的,可以通过质数拆开。

然后是第二个优化,竟然最后k只用到了2,3,5,7,11,13这几个质数。所以被卡题时可以去尝试,看能不能再简化一下数据

然后是最最后一个,,竟然spfa比dijkstra快!我现在终于信spfa了(Orz

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]"
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

const int MX = 1e6 + 10;
const int INF = 0x3f3f3f3f;

int d[MX], vis[MX], n;
int prime[] = 0, 2, 3, 5, 7, 11, 13, prear = 6;

int spfa_bfs(int n)
queue <int> q;
for(int i = 1; i <= n + 10; i++)
d[i] = INF; vis[i] = 0;

d[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 <= prear && x * prime[j] < n + 10; j++)
int y = x * prime[j], cost = prime[j];
if( d[x] + cost < d[y])
d[y] = d[x] + cost;
if(!vis[y])
vis[y] = 1;
q.push(y);



int y = x - 1, cost = 1;
if( d[x] + cost < d[y])
d[y] = d[x] + cost;
if(!vis[y])
vis[y] = 1;
q.push(y);



return d[n];


int main()
//FIN;
scanf("%d", &n);
printf("%d\\n", spfa_bfs(n));
return 0;



以上是关于最短路 51Nod1693 水群的主要内容,如果未能解决你的问题,请参考以下文章

51nod1693 水群 最短路

51nod 1693 水群

51nod1693 水群

51nod 1693 水群(Dijkstra)

51nod1693

51nod 1683 最短路