51nod 1693 水群(spfa最短路)

来源:互联网 发布:java nanotime 转换 编辑:程序博客网 时间:2024/06/06 04:28

Description

总所周知,水群是一件很浪费时间的事,但是其实在水群这件事中,也可以找到一些有意思的东西。
比如现在,bx2k就在研究怎样水表情的问题。
首先,bx2k在对话框中输入了一个表情,接下来,他可以进行三种操作。
第一种,是全选复制,把所有表情全选然后复制到剪贴板中。
第二种,是粘贴,把剪贴板中的表情粘贴到对话框中。
第三种,是退格,把对话框中的最后一个表情删去。
假设当前对话框中的表情数是num0,剪贴板中的表情数是num1,
那么第一种操作就是num1=num0
第二种操作就是num0+=num1
第三种操作就是num0–
现在bx2k想知道,如果要得到n(1<=n<=10^6)个表情,最少需要几次操作。
请你设计一个程序帮助bx2k水群吧。

Input

一个整数n表示需要得到的表情数

Output

一个整数ans表示最少需要的操作数

Input示例

233

Output示例

17

解题思路

可以结合题意先思考一个简单问题,对于A=B*k,如果将一个数B转化为A满足这样一个等式,就可以将B复制一次,然后粘贴k-1次,一共操作k次,这样从B便可延伸出k-1个分支,当然这并不是简单的优化。对于数k=p1p2p3(pi),这样就可以先将B复制一次粘贴p1-1次,然后将(B*p1)复制一次粘贴p2-1次,这样分支数便减少为(p1+p2+p3+……);但是还存在一种情况,就是对p进行质因子分解的时候只需要2,3,5,7,11这样前5个即可,原因大概就是例如46=223,但是23=241=22231,即将23步优化为了10步,所以在扩展时只扩展 B2,B3,B5,B7,B11这样五个节点即可,另外对应退格键的分支是B-1。根据这种扩展规则进行建图,求1-n的最短路即可。

代码实现

#include<bits/stdc++.h>using namespace std;#define ll long long#define INF 0x3f3f3f3f#define maxn 1000007bool vis[maxn];int dis[maxn],n;int a[]={2,3,5,7,11};void spfa(){    memset(vis,0,sizeof(vis));    memset(dis,INF,sizeof(dis));    queue<int>qu;    qu.push(1);    vis[1]=1;    dis[1]=0;    while(!qu.empty())    {        int t=qu.front();        qu.pop();        vis[t]=0;        if(t-1>0&&dis[t-1]>dis[t]+1)        {            dis[t-1]=dis[t]+1;            if(!vis[t-1])            {                qu.push(t-1);                vis[t-1]=1;            }        }        for(int i=0;i<5;i++)        {            if(t*a[i]<maxn&&dis[t*a[i]]>dis[t]+a[i])            {                dis[t*a[i]]=dis[t]+a[i];                if(!vis[t*a[i]])                {                    qu.push(t*a[i]);                    vis[t*a[i]]=1;                }            }        }    }    printf("%d\n",dis[n]);}int main(){    scanf("%d",&n);    spfa();    return 0;}
原创粉丝点击