给定数字n,m(1<=n,m<=500000)
将n变为n*2花费2,将n变为n-3花费3,要求过程中所有数字都在[1,500000]区间内。
求将n变为m的最少花费
思路:建图
将每个数字视为图中的点,数字之间的转换视为图中的边,有向图。
500000个点,(i,i*2)权值为2,(i,i-3)权值为3
转换为求n至m的最短路径
1 #include <bits/stdc++.h> 2 using namespace std; 3 const long long INF = 0x3f3f3f3f3f3f3f3f; 4 int n,m; 5 vector<pair<long long,int>> edge[500001]; 6 long long dis[500001]; 7 typedef pair<long long,int> P;//first 最短距离,second顶点编号 8 9 void dijkstra(int s) 10 { 11 memset(dis,INF, sizeof(dis)); 12 priority_queue<P,vector<P>,greater<P>> que; //最小堆 13 que.push(P(0,s)); 14 dis[s]=0; 15 while(que.size()) 16 { 17 P p=que.top();que.pop(); 18 int v = p.second; 19 //vis[v]=1; 20 if(dis[v]<p.first)continue; 21 for(int i=0;i<edge[v].size();i++) 22 { 23 int to = edge[v][i].second; 24 long long cost = edge[v][i].first; 25 //if(!vis[to]&&dis[to]>dis[v]+cost) 26 if(dis[to]>dis[v]+cost) 27 { 28 dis[to]=dis[v]+cost; 29 que.push(P(dis[to],to)); 30 } 31 } 32 } 33 if(dis[m]==INF) 34 cout<<-1<<endl; 35 else 36 cout<<dis[m]; 37 } 38 39 int main() { 40 cin >> n >> m; 41 for (int i = 1; i <= 500000; i++) 42 { 43 if(2*i<500000) 44 edge[i].push_back(make_pair(2,2*i)); 45 if(i-3>0) 46 edge[i].push_back(make_pair(3,i-3)); 47 } 48 dijkstra(n); 49 return 0; 50 }
思路2:暴力BFS
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int INF = 0x3f3f3f3f; 4 typedef long long LL; 5 int n,m; 6 struct node 7 { 8 int x; 9 LL cost; 10 }; 11 int vis[500002]; 12 13 int main() { 14 cin >> n >> m; 15 node cur,now; 16 cur.x=n,cur.cost=0; 17 queue<node> q; 18 q.push(cur); 19 LL ans=1e18; 20 vis[cur.x]=1; 21 while(q.size()) 22 { 23 now=q.front();q.pop(); 24 if(now.x==m) 25 { 26 ans=min(ans,now.cost); 27 continue;//剪枝 28 } 29 cur.x=now.x*2; 30 cur.cost=now.cost+2; 31 if(cur.x<=500000&&!vis[cur.x]) 32 { 33 vis[cur.x]=1; 34 q.push(cur); 35 } 36 cur.x=now.x-3; 37 cur.cost=now.cost+3; 38 if(cur.x>0&&!vis[cur.x]) 39 { 40 vis[cur.x]=1; 41 q.push(cur); 42 } 43 } 44 if(ans==1e18) printf("-1 "); 45 else cout<<ans<<endl; 46 return 0; 47 }