- 题意:给你两个数x,y。由x每次可以经过一系列操作变换,每个变换都有一定的费用,求x变换到y的最小费用下最小步数。
- 思路:类似最短路的思想,当时只想到每个点有30个方向可以走,于是直接广搜,但不是TLE就是MLE,后来比完赛看题解才知道要用优先队列。最小费用优先,然后最小步数优先。每一步都是前一步到达的,但一个点可以由多个点到达,这时我们肯定要取最优的那一步嘛。如果我们不用标记,那么就存在重复走的过程,这样TLE和MLE是很合理的,但标记的话如果不用优先队列就可能导致这一步并不是由最优路线得到的,而我们直接就将其堵塞了。。。这个题关键就是这么最短路的思想,而且我们保证第一次到达这个y点一定是最优解,直接return,否则还是会超时的。
- 优先队列 重构结构体。
-
I - Interesting Calculator
UVA - 12664 -
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f int nxt[5][15],x,y,ans,cnt; int vis[100005]; struct node { int num,cost,step; friend bool operator >(node a,node b) { if(a.cost>b.cost) return true; else if(a.cost==b.cost&&a.step>b.step) return true; else return false; } } temp1,temp2; void bfs() { memset(vis,inf,sizeof(vis)); priority_queue<node,vector<node>,greater<node> >q; temp1.cost=0; temp1.num=x; temp1.step=0; q.push(temp1); vis[x]=0; while(!q.empty()) { temp1.num=q.top().num; temp1.cost=q.top().cost; temp1.step=q.top().step; q.pop(); if(temp1.num==y) { ans=temp1.cost; cnt=temp1.step; return ; } else { for(int i=2; i>=0; i--) for(int j=9; j>=0; j--) { if(i==0) { temp2.cost=temp1.cost+nxt[i][j]; temp2.num=temp1.num*10+j; temp2.step=temp1.step+1; } if(i==1) { temp2.cost=temp1.cost+nxt[i][j]; temp2.num=temp1.num+j; temp2.step=temp1.step+1; } if(i==2) { temp2.cost=temp1.cost+nxt[i][j]; temp2.num=temp1.num*j; temp2.step=temp1.step+1; } if(temp2.num>y) continue; else if(temp2.cost<vis[temp2.num]) { vis[temp2.num]=temp2.cost; q.push(temp2); } } } } } int main() { int aaaaa=1; while(cin>>x>>y) { memset(nxt,0,sizeof(nxt)); ans=inf; for(int i=0; i<3; i++) for(int j=0; j<10; j++) cin>>nxt[i][j]; bfs(); cout<<"Case "<<aaaaa++<<": "<<ans<<" "<<cnt<<endl; } return 0; }