题目:uva10067 Playing with Wheels
题意:给出一个机器,有四个循环的轮子。见图,然后给出一个初始数和目标数,然后期间不能出现的数字,每一分钟能够拨动一个数。问你最短须要的时间。
分析:这个题目能够转化为求图的最短路。
由于有对于一个当前状态。有8种能够转化为的状态,那么我们能够把每一种状态转化为一个点,然后状态之间连长度 1 的边,然后求一次初始状态到目标状态的最短路。
開始的时候我们每一组数据建图一次,下来0.9s。然后优化了一下,就是在每次建图不能到达的边删除之后求完之后恢复过来,这样不用每次建图。下来0.19s,时间相当快了。就仅仅是一个spfa的时间复杂度O(m)、
AC代码:
#include <cstdio> #include <iostream> #include <queue> #include <cstring> #include <algorithm> #include <stack> #include <vector> #include <utility> #include <cmath> using namespace std; const int N = 10005; const int M = 10000; const int inf = 0x3f3f3f3f; struct Node { int x,len; }; vector<Node> v[N]; void add_Node(int x,int y,int len) { v[x].push_back((Node){y,len}); v[y].push_back((Node){x,len}); } int count(int i,int j,int k,int f) { return ((i+10)%10)*1000+((j+10)%10)*100+((k+10)%10)*10+(f+10)%10; } int dir[10][5]= { {0,0,0,1},{0,0,0,-1}, {0,0,1,0},{0,0,-1,0}, {0,1,0,0},{0,-1,0,0}, {1,0,0,0},{-1,0,0,0} }; void build(int i,int j,int k,int f) { int tmp=count(i,j,k,f); for(int p=0; p<8; p++) { int tmp1=count(i+dir[p][0],j+dir[p][1],k+dir[p][2],f+dir[p][3]); add_Node(tmp,tmp1,1); } } void isit() { for(int i=0; i<10; i++) for(int j=0; j<10; j++) for(int k=0; k<10; k++) for(int f=0; f<10; f++) build(i,j,k,f); } int dis[N]; void spfa(int s) { int i; queue<int> q; for(i=0; i<N; i++) dis[i]=inf; dis[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(i=0; i<v[u].size(); i++) { Node p=v[u][i]; if(dis[p.x]>dis[u]+p.len) { dis[p.x]=dis[u]+p.len; q.push(p.x); } } } } int dx[N],dy[N],dz[N],dk[N]; int main() { int T; isit(); scanf("%d",&T); while(T--) { int x,y,z,k; scanf("%d%d%d%d",&x,&y,&z,&k); int st=x*1000+y*100+z*10+k; scanf("%d%d%d%d",&x,&y,&z,&k); int en=x*1000+y*100+z*10+k; int cc; scanf("%d",&cc); for(int i=0;i<cc;i++) { scanf("%d%d%d%d",&dx[i],&dy[i],&dz[i],&dk[i]); int tmp=count(dx[i],dy[i],dz[i],dk[i]); v[tmp].clear(); } spfa(st); if(dis[en]>=inf) puts("-1"); else printf("%d ",dis[en]); for(int i=0;i<cc;i++) { build(dx[i],dy[i],dz[i],dk[i]); } } }